.Net 4.0新特性之Dynamic 动态类型(转载)
2010-12-11 10:32 爱研究源码的javaer 阅读(308) 评论(0) 编辑 收藏 举报一、.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内就可以看见该类的成员列表,截图如下:
所属方法都是虚方法,我们可以重写这些虚方法。这里主要看TryInvokeMember()方法。这个方法VS2010给出了详细的描述。
.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
程序执行结果如下:
转自: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