zoukankan      html  css  js  c++  java
  • .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
  • 相关阅读:
    我们工作为了什么
    为什么去国企(HP中华区总裁孙振耀退休感言)
    android中的所有activity间动画跳转
    [转]Eclipse进行可视化的GUI开发3大GUI插件
    用Monkey测试android程序
    大学之后拉开差距的原因
    dataset 和 datareader 区别
    曾经运行该线程的应用程序域已卸载。
    guid.tostring() 格式化指南
    vs 使用技巧
  • 原文地址:https://www.cnblogs.com/johnwonder/p/1902830.html
Copyright © 2011-2022 走看看