.NET 4.0 之 Dynamic 動態類型
一、.NET4.0主要新特性
.NET4.0在.Net3.5基礎上新增的主要特性有:可選參數、命名參數和Dynamic。具體請閱生魚片的這篇博文。這里我們著重講解C#4.0的Dynamic特性,對于其他特性大家可以在VS2010內嘗試一下。總之.Net在不斷進步中。
二、ExpandoObject普通應用
ExpandoObject 類,“需引用System.Dynamic命名空間” 。請看以下代碼:
Customer.Name = "Lucy";
Customer.Age = 20;
Customer.Female = true;
Console.WriteLine(Customer.Name + Customer.Age + Customer.Female);
Console.ReadKey();
輸出<< Lucy20True,這里已經類似javascript 的var obj ={}; obj.Name ='lucy'。但又不完全相同,因為不能在clr運行時動態生成屬性或者方法。但至少比.NET3.5先進了。
三、Dynamic 動態類型對DuckType 的支持
1.前不久看過這么一段代碼:
{
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這段代碼片段:
if (obj && typeof obj.ourMethod === "function") {
return obj.ourMethod();
}
alert('未找到!');
return null;
}
var ourObj1 = {};
ourObj1.Method = function () {
alert('111');
};
var ourObj2
= {};ourObj2.ourMethod = function () {
alert('已經找到ourMethod并且執行');
};
tryInvokeMember(ourObj1);
tryInvokeMember(ourObj2);
大家讀完這段js代碼后應該會明白為什么我要重點討論C#4.0中的DynamicObject了吧?真正的目的就是:在DuckType 類(鴨子) 方法(鴨子叫)執行之前,我們要判斷對象的類是否是具備鴨子叫的功能?如果不具備就不應該執行,否則程序勢必會拋出異常。C#中如何實現呢?步驟如下:
1、建立DynamicAnimal 類繼承DynamicObject類,并且重寫TryInvokeMember虛方法:
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:
{
public string Quack()
{
return "鴨子嘛,就Quack吧!";
}
}
public class Human : DynamicAnimal
{
public string Talk()
{
return "人類是用Talk,而不是Quack";
}
}
3、在Console 內 建立DuckType的調用方法:
{
string result = animal.Quack();
return result ?? "...人類當然不會鴨叫...";
}
4、Console 內 Main方法調用:
{
var duck = new Duck();
var cow = new Human();
Console.WriteLine("鴨子是Quack");
Console.WriteLine(DoQuack(duck));
Console.WriteLine("人類是talk");
Console.WriteLine(DoQuack(cow));
Console.ReadKey();
}
程序執行結果如下:
您是否對.Net4.0 Dynamic 這個動態類型有了一個新的認識呢?