C#4.0 新特性 动态类型Dynamic

转自 http://www.cnblogs.com/ryanding/archive/2010/12/09/1900106.html



        本文主要旨在与网友分享.Net4.0的Dynamic 对Duck Type 的支持。

    一、.net4.0主要新特性


        .Net4.0在.Net3.5基础上新增的主要特性有:可选参数、命名参数和Dynamic。具体请阅生鱼片的这篇博文。这里我们着重讲解C#4.0的Dynamic特性,对于其他特性大家可以在VS2010内尝试一下。总之.Net在不断进步中。

     二、ExpandoObject普通应用  


       ExpandoObject 类,“需引用System.Dynamic命名空间” 。请看以下代码:       

复制代码
 
    
1 dynamic Customer = new ExpandoObject(); 2 Customer.Name = " Lucy " ; 3 Customer.Age = 20 ; 4 Customer.Female = true ; 5 Console.WriteLine(Customer.Name + Customer.Age + Customer.Female); 6 Console.ReadKey();    
复制代码

输出<< Lucy20True,这里已经类似javascript 的var obj ={}; obj.Name ='lucy'。但又不完全相同,因为不能在clr运行时动态生成属性或者方法。但至少比.NET3.5先进了。

    三、Dynamic 动态类型对DuckType 的支持


      1.前不久在园子里面看见了thinking的这篇博文,文中有这么一段代码:

复制代码
 
    
static class Calculator { public static T Add < T > (T t1, T t2) { dynamic d1 = t1; dynamic d2 = t2; return (T)(d1 + d2); } } public static void Main( string [] args){ int i = Calculator.Add( 1 , 2 ); double d = Calculator.Add( 1.1 , 2.2 ); string s = Calculator.Add( " abc " , " def " ); Console.WriteLine(i + " " + d + " " + s); }
复制代码

输出:

>>3 3.3 abcdef

作者在文中指出了以上C#代码是为了通过动态类型来实现基于duck typing的泛型参数约束

为了在C#支持Duck Type还有一个重要的.Net4.0特性有必要提及到,这也是本文重点讨论的内容。

它就是:“DynamicObject” 该类位于System.Dynamic 命名空间下。在VS2010内就可以看见该类的成员列表,截图如下:

所属方法都是虚方法,我们可以重写这些虚方法。这里主要看TryInvokeMember()方法。这个方法VS2010给出了详细的描述。

根据VS2010注释,由于我的VS2010是英文版的,这里就不贴出英文注释了。简单介绍一下如何使用这个方法:假设我们一个类OurClass它继承了DynamicObject 这个Class。OurClass中有一个方法OurMethod()。接着在OurClass 类中 重写 TryInvokeMember这个基类虚方法。以上设置完后以后只要OurClass 的OurMethod方法一旦被调用都先执行一下重写后的

     TryInvokeMember()方法。也许您会问这样到底有何用途?OK!请先看javascript这段代码片段:

复制代码
 
    
1 function tryInvokeMember(obj) { 2 if (obj && typeof obj.ourMethod === " function " ) { 3 return obj.ourMethod(); 4 } 5 alert( ' 未找到! ' ); 6 return null ; 7 } 8 9 var ourObj1 = {}; 10 ourObj1.Method = function () { 11 alert( ' 111 ' ); 12 }; 13 14 var ourObj2 = {}; 15 ourObj2.ourMethod = function () { 16 alert( ' 已经找到ourMethod并且执行 ' ); 17 }; 18 19 tryInvokeMember(ourObj1); 20 tryInvokeMember(ourObj2);
复制代码
大家读完 这段 js代码后应该会明白为什么我要重点讨论C#4.0中的DynamicObject了吧?真正的目的就是:在DuckType 类(鸭子) 方法(鸭子叫)执行之前,我们要判断对象的类是否是具备鸭子叫的功能?如果不具备就不应该执行,否则程序势必会抛出异常。C#中如何实现呢?步骤如下:

      1、建立DynamicAnimal 类继承DynamicObject类,并且重写TryInvokeMember虚方法:

复制代码
 
    
public class DynamicAnimal : DynamicObject { public override bool TryInvokeMember(InvokeMemberBinder binder, object [] args, out object result) { bool success = base .TryInvokeMember(binder, args, out result); // 如果方法不存在,请将result 这个out参数赋值为null if ( ! success) result = null ; // 如果这个地方返回false 将会引发异常 return true ; } }
复制代码

     2、建立两个DuckType类,分别为Duck 和 Human:

复制代码
 
    
1 public class Duck : DynamicAnimal 2 { 3 public string Quack() 4 { 5 return " 鸭子嘛,就Quack吧! " ; 6 } 7 } 8   public class Human : DynamicAnimal 9 { 10 public string Talk() 11 { 12 return " 人类是用Talk,而不是Quack " ; 13 } 14 }
复制代码

    3、在Console 内 建立DuckType的调用方法:

 
    
1 public static string DoQuack(dynamic animal) 2 { 3 string result = animal.Quack(); 4 return result ?? " ...人类当然不会鸭叫... " ; 5 }
    4、Console 内 Main方法调用:

复制代码
 
    
1 static void Main( string [] args) 2 { 3 var duck = new Duck(); 4 var cow = new Human(); 5 Console.WriteLine( " 鸭子是Quack " ); 6 Console.WriteLine(DoQuack(duck)); 7 Console.WriteLine( " 人类是talk " ); 8 Console.WriteLine(DoQuack(cow)); 9 Console.ReadKey(); 10 }
复制代码
程序 执行结果 如下:


猜你喜欢

转载自blog.csdn.net/CommandBaby/article/details/51776771
今日推荐