.Net 4.0新特性之Dynamic 动态类型(转载)

一、.net4.0主要新特性
  .Net4.0在.Net3.5基础上新增的主要特性有:可选参数、命名参数和Dynamic。具体请阅生鱼片的这篇博文。这里我们着重讲解C#4.0的Dynamic特性,对于其他特性大家可以在VS2010内尝试一下。总之.Net在不断进步中。
  二、ExpandoObject普通应用
  ExpandoObject 类,“需引用System.Dynamic命名空间” 。请看以下代码:$ w# H; h0 D5 t/ v, O4 w& g6 k
dynamic Customer =
new ExpandoObject();# I9 l3 M! z; q5 v- ], F1 f
Customer.Name =
"Lucy";. v' G8 M2 i: _# p; R# y
Customer.Age =
20;
Customer.Female =7 E. J& z7 t; R4 I) m' b$ W
true;5 ~1 S& @, {7 n' Q( u' c
Console.WriteLine(Customer.Name + Customer.Age + Customer.Female);
Console.ReadKey();) X2 Y8 ~1 K8 d
, S  r( n. {  a+ n' N
5 D! |+ |; F% l7 _, V; G5 {4 v  D- m
  输出<< Lucy20True,这里已经类似javascript 的var obj ={}; obj.Name ='lucy'。但又不完全相同,因为不能在clr运行时动态生成属性或者方法。但至少比.NET3.5先进了。; Z0 M# g1 J9 e3 H6 F: s" D
  三、Dynamic 动态类型对DuckType 的支持
  1.前不久看过这么一段代码:/ N- G* d% `2 `6 O9 m
static class Calculator & K6 ?8 S0 G6 K  l. B* J
{   
public static T Add<T>(T t1, T t2) {        , L4 h# i& Q9 ]4 ?: h
dynamic d1 = t1;        & n# a, Y2 z1 h* ?  Y
dynamic d2 = t2;        
return (T)(d1 + d2);    4 X% n+ O9 q6 I2 i
   }
}* U9 j0 u2 o0 V
public static void Main(string[] args){   1 Q) N" ~4 r' e  e% }: h! H3 k4 E
  int i = Calculator.Add(1, 2);   
  double d = Calculator.Add(1.1, 2.2);    ; p/ @; M  `0 W$ E
  string s = Calculator.Add("abc", "def");     
  Console.WriteLine(i +
"& O1 m, y+ {3 ~. F) t
"
+ d +
"- e0 {2 n. I0 `- |$ ?
": ?+ {7 `# X+ `# H7 s/ q
+ s);( l+ X$ U6 W/ F- @% R& m' ^4 L0 O
}+ D! B6 _% Y  K1 M, a4 [


  输出:
  >>3 3.3 abcdef
  作者在文中指出了以上C#代码是为了通过动态类型来实现基于duck typing的泛型参数约束。2 G# U7 k; D9 N* l, d8 H  ~
  为了在C#支持Duck Type还有一个重要的.Net4.0特性有必要提及到,这也是本文重点讨论的内容。5 h. O2 x& v# G
  它就是:“DynamicObject” 该类位于System.Dynamic 命名空间下。在VS2010内就可以看见该类的成员列表,截图如下:

; c9 q5 k' u& U0 ?6 k+ l


  所属方法都是虚方法,我们可以重写这些虚方法。这里主要看TryInvokeMember()方法。这个方法VS2010给出了详细的描述。  
根据VS2010注释,由于我的VS2010是英文版的,这里就不贴出英文注释了。简单介绍一下如何使用这个方法:假设我们一个类OurClass它继承 了DynamicObject 这个Class。OurClass中有一个方法OurMethod()。接着在OurClass 类中 重写 TryInvokeMember这个基类虚方法。以上设置完后以后只要OurClass 的OurMethod方法一旦被调用都先执行一下重写后的
  TryInvokeMember()方法。也许您会问这样到底有何用途?OK!请先看javascript这段代码片段:% h! _9 Q# S# Z& G
/ h5 E+ \9 x8 ?  r5 K, v
function tryInvokeMember(obj) { + R! _- _  X. c5 l
             if (obj && typeof obj.ourMethod ===
"function") { . U) j9 r8 F) P8 A6 `; y9 n
                 return obj.ourMethod();
             } 6 }" q3 v( A7 Y5 L8 O
            alert('未找到!'); * S$ S, B% t! o, s& J! f
            return null;
         } " X/ ]! b  b" b* K
  / Z- i- q. s% T% X. q& S
         var ourObj1 = {};$ E, `) [/ y: u8 X
         ourObj1.Method =$ ?; I; I3 |" C2 x* r6 v
function () {
            alert('111');) {) v+ r+ U' n  u  E; p
         };

         var ourObj2 = {};
         ourObj2.ourMethod =
function () {+ P3 C, S; b. c/ P: ^
             alert('已经找到ourMethod并且执行');
         };

         tryInvokeMember(ourObj1);
         tryInvokeMember(ourObj2);
9 F/ Z8 E( w5 p0 b# C% `2 O+ h4 R- Q

  大家读完这段js代码 后应该会明白为什么我要重点讨论C#4.0中的DynamicObject了吧?真正的目的就是:在DuckType 类(鸭子) 方法(鸭子叫)执行之前,我们要判断对象的类是否是具备鸭子叫的功能?如果不具备就不应该执行,否则程序势必会抛出异常。C#中如何实现呢?步骤如下:8 y  t" q& N0 i( W4 t& M: e
  1、建立DynamicAnimal 类继承DynamicObject类,并且重写TryInvokeMember虚方法:% _1 u) O) C7 O" \6 F' J2 K( W
public class DynamicAnimal : DynamicObject    {        
      public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)        0 \' W4 Q/ j' J6 F3 @
    {            
       bool success = base.TryInvokeMember(binder, args, out result);           1 w2 ]7 u8 D6 r8 X9 o: X
        //如果方法不存在,请将result 这个out参数赋值为null            
        if (!success)               
        result =( z- f! R- D3 d; B0 q
null;           " \; Y9 H/ L. n4 C& f
         //如果这个地方返回false 将会引发异常            $ C. q% X, }1 x  w* ?5 m: S
        return true;       q6 e+ j& g' f) Q0 ?" B
   }   1 X/ M3 d; r* H5 o
}2 E; U0 E; c2 `& Q4 }4 B+ k


  2、建立两个DuckType类,分别为Duck 和 Human:3 c6 r/ V3 F6 X' l
public class Duck : DynamicAnimal
     { 2 L& Q0 \+ a( d# `  S0 t% t! i& \, i
         public
string Quack() / n: n/ c! h- I$ l
         { ) S4 r: g+ s% Y5 N9 L" Q( H$ b: x% q
            return "鸭子嘛,就Quack吧!"; ; u; ?/ I# p$ f% D" {: e
         }
     }1 V3 h- R) E; I. N- _
  public class Human : DynamicAnimal ) V0 }/ H" ]+ [! b% V1 u" t" |3 O# w
     {
         public: e; L% Z8 D0 G! C+ ?
string Talk()
         {
             return "人类是用Talk,而不是Quack";! X' k+ U$ U# _
         }" w9 ]7 L. y9 P
     }

; Q, U- X# E4 n9 n' D7 @% ~" _
  3、在Console 内 建立DuckType的调用方法:. C4 K1 a' }, P# i
public static string DoQuack(dynamic animal)
         {
             string result = animal.Quack();
             return result ?? "...人类当然不会鸭叫...";% x' X  o% ]" J; \8 b: z7 _" x
         }+ c5 j: ]; B- k: s) e! ?

7 A  x) Q# v0 @' b! l) `/ o
  4、Console 内 Main方法调用:
static void Main(string[] args) , |" c- W* h( X0 U+ t2 n6 s
         { 5 G4 A. ^- s8 w3 ]2 b8 b! p# [' T
             var duck =
new Duck();
             var cow =/ \+ M3 H/ H" i: C& O' c
new Human();
             Console.WriteLine("鸭子是Quack"); 8 D: P! f  w+ I; S4 p& U# e9 M
             Console.WriteLine(DoQuack(duck)); 1 b9 r8 {: w8 z4 C/ O$ {$ q
             Console.WriteLine("人类是talk");
             Console.WriteLine(DoQuack(cow)); 5 I0 C( E$ L' I0 ~( y" b$ T
             Console.ReadKey();        ) ?3 }6 C% T4 o
}
9 K1 l8 ]+ {+ Y3 @# J+ Q
1 w" S& R+ |" [6 g% q- q  K) U) e
  程序执行结果如下:
转自:
http://tech.techweb.com.cn/thread-463640-1-1.html
原文地址:https://www.cnblogs.com/johnwonder/p/1902830.html