本專(zhuān)題概要:
創(chuàng)新互聯(lián)長(zhǎng)期為上1000+客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏(yíng)平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為南京企業(yè)提供專(zhuān)業(yè)的網(wǎng)站制作、網(wǎng)站建設(shè),南京網(wǎng)站改版等技術(shù)服務(wù)。擁有十多年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
引言:
終于迎來(lái)了我們C# 4中特性了,C# 4主要有兩方面的改善——Com 互操作性的改進(jìn)和動(dòng)態(tài)類(lèi)型的引入,然而COM互操作性這里就不詳細(xì)介紹的,對(duì)于.Net 互操作性我將會(huì)在另外一個(gè)專(zhuān)題中詳細(xì)和大家分享下我所了解到的知識(shí),本專(zhuān)題就和大家分享C# 4中的動(dòng)態(tài)類(lèi)型,對(duì)于動(dòng)態(tài)類(lèi)型,我剛聽(tīng)到這個(gè)名詞的時(shí)候會(huì)有這些疑問(wèn)的——動(dòng)態(tài)類(lèi)型到底是什么的呢? 知道動(dòng)態(tài)類(lèi)型大概是個(gè)什么的時(shí)候,肯定又會(huì)有這樣的疑問(wèn)——C# 4中為什么要引入動(dòng)態(tài)類(lèi)型的?(肯定引入之后可以完成我們之前不能做的事情了,肯定是有好處的),下面就具體介紹了動(dòng)態(tài)類(lèi)型有哪些內(nèi)容的。
一、動(dòng)態(tài)類(lèi)型介紹
提到動(dòng)態(tài)類(lèi)型當(dāng)然就要說(shuō)下靜態(tài)類(lèi)型了,對(duì)于什么是靜態(tài)類(lèi)型呢? 大家都知道之前C#一直都是靜態(tài)語(yǔ)言(指定的是沒(méi)有引入動(dòng)態(tài)類(lèi)型之前,這里說(shuō)明下,不是引入了動(dòng)態(tài)類(lèi)型后C#就是動(dòng)態(tài)語(yǔ)言,只是引入動(dòng)態(tài)類(lèi)型后,為C#語(yǔ)言增添了動(dòng)態(tài)語(yǔ)言的特性,C#仍然是靜態(tài)語(yǔ)言),之所以稱(chēng)為靜態(tài)語(yǔ)言,之前我們寫(xiě)代碼時(shí),例如 int i =5;這樣的代碼,此時(shí)i 我們已經(jīng)明確知道它的類(lèi)型為int了,然而這樣的代碼,變量的類(lèi)型的確定是在編譯時(shí)確定的,對(duì)應(yīng)的,如果類(lèi)型的確定是在執(zhí)行時(shí)才確定的類(lèi)型,這樣的類(lèi)型就是動(dòng)態(tài)類(lèi)型(C# 4.0中新添加了一個(gè)dynamic 關(guān)鍵字來(lái)定義我們的動(dòng)態(tài)類(lèi)型)。面對(duì)動(dòng)態(tài)類(lèi)型,C#編譯器做的工作只是完成檢查語(yǔ)法是否正確,但無(wú)法確定所調(diào)用的方法或?qū)傩允欠裾_(之所以會(huì)這樣,主要還是因?yàn)閯?dòng)態(tài)類(lèi)型是運(yùn)行時(shí)才知道它的具體類(lèi)型,所以編譯器編譯的時(shí)候肯定不知道類(lèi)型,就沒(méi)辦法判斷調(diào)用的方法或?qū)傩允遣皇谴嬖诤驼_了,所以對(duì)于動(dòng)態(tài)類(lèi)型,將不能使用VS提供的智能提示的功能,這樣寫(xiě)動(dòng)態(tài)類(lèi)型代碼時(shí)就要求開(kāi)發(fā)人員對(duì)于某個(gè)動(dòng)態(tài)類(lèi)型必須準(zhǔn)確知道其類(lèi)型后和所具有的方法和屬性了,不能這些錯(cuò)誤只能在運(yùn)行程序的過(guò)程拋出異常的方式被程序員所發(fā)現(xiàn)。)
補(bǔ)充: 講到dynamic關(guān)鍵字,也許大家會(huì)想到C# 3中的var關(guān)鍵字,這里這里補(bǔ)充說(shuō)明下dynamic, var區(qū)別。var 關(guān)鍵字不過(guò)是一個(gè)指令,它告訴編譯器根據(jù)變量的初始化表達(dá)式來(lái)推斷類(lèi)型。(記住var并不是類(lèi)型),而C# 4中引入的dynamic是類(lèi)型,但是編譯時(shí)不屬于CLR類(lèi)型(指的int,string,bool,double等類(lèi)型,運(yùn)行時(shí)肯定CLR類(lèi)型中一種的),它是包含了System.Dynamic.DynamicAttribute特性的System.Object類(lèi)型,但與object又不一樣,不一樣主要體現(xiàn)在動(dòng)態(tài)類(lèi)型不會(huì)在編譯時(shí)時(shí)執(zhí)行顯式轉(zhuǎn)換,下面給出一段代碼代碼大家就會(huì)很容易看出區(qū)別了:
- object obj = 10;
- Console.WriteLine(obj.GetType());
- // 使用object類(lèi)型此時(shí)需要強(qiáng)制類(lèi)型轉(zhuǎn)換,不能編譯器會(huì)出現(xiàn)編譯錯(cuò)誤
- obj = (int)obj + 10;
- dynamic dynamicnum = 10;
- Console.WriteLine(dynamicnum.GetType());
- // 對(duì)于動(dòng)態(tài)類(lèi)型而言,編譯時(shí)編譯器根本不知道它是什么類(lèi)型,
- // 所以編譯器就判斷不了dynamicnum的類(lèi)型了,所以下面的代碼不會(huì)出現(xiàn)編譯時(shí)錯(cuò)誤
- // 因?yàn)閐ynamicnum有可能是int類(lèi)型,編譯器不知道該變量的具體類(lèi)型不能憑空推測(cè)類(lèi)型
- // 當(dāng)然也就不能提示我們編譯時(shí)錯(cuò)誤了
- dynamicnum = dynamicnum + 10;
二、為什么需要?jiǎng)討B(tài)類(lèi)型
第一部分和大家介紹了什么是動(dòng)態(tài)類(lèi)型,對(duì)于動(dòng)態(tài)類(lèi)型,總結(jié)為一句話(huà)為——運(yùn)行時(shí)確定的類(lèi)型。然而大家了解了動(dòng)態(tài)類(lèi)型到底是什么之后,當(dāng)然又會(huì)出現(xiàn)新的問(wèn)題了,即動(dòng)態(tài)類(lèi)型有什么用的呢? C# 為什么好端端的引入動(dòng)態(tài)類(lèi)型增加程序員的負(fù)擔(dān)呢? 事實(shí)并不是這樣的,下面就介紹了動(dòng)態(tài)類(lèi)型到底有什么用,它并不是所謂給程序員帶來(lái)負(fù)擔(dān),一定程度上講是福音
2.1 使用動(dòng)態(tài)類(lèi)型可以減少?gòu)?qiáng)制類(lèi)型轉(zhuǎn)換
從第一部分的補(bǔ)充也可以看到,使用動(dòng)態(tài)類(lèi)型不需要類(lèi)型轉(zhuǎn)換是因?yàn)榫幾g器根本在編譯時(shí)的過(guò)程知道什么類(lèi)型,既然不知道是什么類(lèi)型,怎么判斷該類(lèi)型是否能進(jìn)行什么操作,所以也就不會(huì)出現(xiàn)類(lèi)似“運(yùn)算符“+”無(wú)法應(yīng)用于“object”和“int”類(lèi)型的操作數(shù)“或者”不存在int類(lèi)型到某某類(lèi)型的隱式轉(zhuǎn)換“的編譯時(shí)錯(cuò)誤了,可能這點(diǎn)用戶(hù),開(kāi)發(fā)人員可能并不覺(jué)得多好的,因?yàn)閯?dòng)態(tài)類(lèi)型沒(méi)有智能提示的功能。 但是動(dòng)態(tài)類(lèi)型減少了強(qiáng)制類(lèi)型轉(zhuǎn)換的代碼之后,可讀性還是會(huì)有所增強(qiáng)。(這里又涉及到個(gè)人取舍問(wèn)題的, 如果自己覺(jué)得那種方式方便就用那種的,沒(méi)必要一定要用動(dòng)態(tài)類(lèi)型,主要是看那種方式可以讓自己和其他開(kāi)發(fā)人員更好理解)
2.2 使用動(dòng)態(tài)類(lèi)型可以使C#靜態(tài)語(yǔ)言中調(diào)用Python等動(dòng)態(tài)語(yǔ)言
對(duì)于這點(diǎn),可能朋友有個(gè)疑問(wèn),為什么要在C#中使用Python這樣的動(dòng)態(tài)語(yǔ)言呢? 對(duì)于這個(gè)疑問(wèn),就和在C#中通過(guò)P/Invoke與本地代碼交互,以及與COM互操作的道理一樣,假設(shè)我們要實(shí)現(xiàn)的功能在C#類(lèi)庫(kù)中沒(méi)有,然而在Python中存在時(shí),此時(shí)我們就可以直接調(diào)用Python中存在的功能了。
三、動(dòng)態(tài)類(lèi)型的使用
前面兩部分和大家介紹動(dòng)態(tài)類(lèi)型的一些基礎(chǔ)知識(shí)的,了解完基礎(chǔ)知識(shí)之后,大家肯定很迫不及待地想知道如何使用動(dòng)態(tài)類(lèi)型的,下面給出兩個(gè)例子來(lái)演示動(dòng)態(tài)類(lèi)型的使用的。
3.1 C# 4 通過(guò)dynamic關(guān)鍵字來(lái)實(shí)現(xiàn)動(dòng)態(tài)類(lèi)型
- dynamic dyn = 5;
- Console.WriteLine(dyn.GetType());
- dyn = "test string";
- Console.WriteLine(dyn.GetType());
- dynamic startIndex = 2;
- string substring = dyn.Substring(startIndex);
- Console.WriteLine(substring);
- Console.Read();
運(yùn)行結(jié)果為:
3.2 在C#中調(diào)用Python動(dòng)態(tài)語(yǔ)言(要運(yùn)行下面的代碼,必須下載并安裝IronPython,IronPython 是在 .NET Framework 上實(shí)現(xiàn)的第一種動(dòng)態(tài)語(yǔ)言。http://ironpython.codeplex.com下載 )
- // 引入動(dòng)態(tài)類(lèi)型之后
- // 可以在C#語(yǔ)言中與動(dòng)態(tài)語(yǔ)言進(jìn)行交互
- // 下面演示在C#中使用動(dòng)態(tài)語(yǔ)言Python
- ScriptEngine engine = Python.CreateEngine();
- Console.Write("調(diào)用Python語(yǔ)言的print函數(shù)輸出: ");
- // 調(diào)用Python語(yǔ)言的print函數(shù)來(lái)輸出
- engine.Execute("print 'Hello world'");
- Console.Read();
運(yùn)行結(jié)果:
四、動(dòng)態(tài)類(lèi)型背后的故事
知道了如何在C#中調(diào)用動(dòng)態(tài)語(yǔ)言之后,然而為什么C# 為什么可以使用動(dòng)態(tài)類(lèi)型呢?C#編譯器到底在背后為我們動(dòng)態(tài)類(lèi)型做了些什么事情的呢? 對(duì)于這些問(wèn)題,答案就是DLR(Dynamic Language Runtime,動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí)),DLR使得C#中可以調(diào)用動(dòng)態(tài)語(yǔ)言以及使用dynamic的動(dòng)態(tài)類(lèi)型。提到DLR時(shí),可能大家會(huì)想到.Net Framework中的CLR(公共語(yǔ)言運(yùn)行時(shí)),然而DLR 與CLR到底是什么關(guān)系呢?下面就看看.Net 4中的組件結(jié)構(gòu)圖,相信大家看完之后就會(huì)明白兩者之間的區(qū)別:
從圖中可以看出,DLR是建立在CLR的基礎(chǔ)之上的,其實(shí)動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí)是動(dòng)態(tài)語(yǔ)言和C#編譯器用來(lái)動(dòng)態(tài)執(zhí)行代碼的庫(kù),它不具有JIT編譯,垃圾回收等功能。然而DLR在代碼的執(zhí)行過(guò)程中扮演的是什么樣的角色呢? DLR所扮演的角色就是——DLR通過(guò)它的綁定器(binder)和調(diào)用點(diǎn)(callsite),元對(duì)象來(lái)把代碼轉(zhuǎn)換為表達(dá)式樹(shù),然后再把表達(dá)式樹(shù)編譯為IL代碼,最后由CLR編譯為本地代碼(DLR就是幫助C#編譯器來(lái)識(shí)別動(dòng)態(tài)類(lèi)型)。這里DLR扮演的角色并不是憑空想象出來(lái)的,而且查看它的反編譯代碼來(lái)推出來(lái)的,下面就具體給出一個(gè)例子來(lái)說(shuō)明DLR背后所做的事情。C#源代碼如下:
- class Program
- {
- static void Main(string[] args)
- {
- dynamic text = "test text";
- int startIndex = 2;
- string substring = text.Substring(startIndex);
- Console.Read();
- }
- }
通過(guò)Reflector工具查看生成的IL代碼如下:
- private static void Main(string[] args)
- {
- object text = "test text";
- int startIndex = 2;
- if (<Main>o__SiteContainer0.<>p__Site1 == null)
- {
- // 創(chuàng)建用于將dynamic類(lèi)型隱式轉(zhuǎn)換為字符串的調(diào)用點(diǎn) <Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(string), typeof(Program)));
- }
- if (<Main>o__SiteContainer0.<>p__Site2 == null)
- {
- // 創(chuàng)建用于調(diào)用Substring函數(shù)的調(diào)用點(diǎn) <Main>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, int, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "Substring", null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
- }
- // 調(diào)用調(diào)用點(diǎn),首先調(diào)用<>p_Site2,即Substring方法,再調(diào)用<>P_Site1來(lái)將結(jié)果進(jìn)行轉(zhuǎn)換 string substring = <Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, <Main>o__SiteContainer0.<>p__Site2.Target(<Main>o__SiteContainer0.<>p__Site2, text, startIndex));
- Console.Read();
- }
- //編譯器生成的內(nèi)嵌類(lèi)型為
- [CompilerGenerated]
- private static class <Main>o__SiteContainer0
- {
- // Fields
- public static CallSite<Func<CallSite, object, string>> <>p__Site1;
- public static CallSite<Func<CallSite, object, int, object>> <>p__Site2;
- }
從IL代碼中可以看出Main方法內(nèi)包含兩個(gè)動(dòng)態(tài)操作,因?yàn)榫幾g器生成的內(nèi)嵌類(lèi)型包含兩個(gè)調(diào)用點(diǎn)(CallSite<T>,CallSite<T>即是System.Runtime.CompilerServices命名空間下的一個(gè)類(lèi),關(guān)于CallSite的具體信息可以查看MSDN中的介紹——CallSite<T> )字段,一個(gè)是調(diào)用Substring方法(即<>p__Site2),一個(gè)是將結(jié)果(編譯時(shí)時(shí)dynamic)動(dòng)態(tài)地轉(zhuǎn)換為字符串(即<>p__Site1),下面給出動(dòng)態(tài)類(lèi)型的執(zhí)行過(guò)程(注意DLR中有一個(gè)緩存的概念):
五、動(dòng)態(tài)類(lèi)型的約束
相信通過(guò)前面幾部分的介紹大家已經(jīng)對(duì)動(dòng)態(tài)類(lèi)型有了一定的了解的,尤其是第四部分的介紹之后,大家應(yīng)該對(duì)于動(dòng)態(tài)類(lèi)型的執(zhí)行過(guò)程也有了一個(gè)清晰的認(rèn)識(shí)了,然而有些函數(shù)時(shí)不能通過(guò)動(dòng)態(tài)綁定來(lái)進(jìn)行調(diào)用的,這里就涉及到類(lèi)型類(lèi)型的約束:
5.1 不能用動(dòng)態(tài)類(lèi)型作為參數(shù)調(diào)用擴(kuò)展方法
不能用動(dòng)態(tài)類(lèi)型作為參數(shù)來(lái)調(diào)用擴(kuò)展方法的原因是——調(diào)用點(diǎn)知道編譯器所知道的靜態(tài)類(lèi)型,但是它不知道調(diào)用所在的源文件在哪里,以及using指令引入了哪些命名空間,所以在編譯時(shí)調(diào)用點(diǎn)就找不到哪些擴(kuò)展方法可以使用,所以就會(huì)出現(xiàn)編譯時(shí)錯(cuò)誤。下面給出一個(gè)簡(jiǎn)單的示例程序:
- var numbers = Enumerable.Range(10, 10);
- dynamic number = 4;
- var error = numbers.Take(number); // 編譯時(shí)錯(cuò)誤
- // 通過(guò)下面的方式來(lái)解決這個(gè)問(wèn)題
- // 1. 將動(dòng)態(tài)類(lèi)型轉(zhuǎn)換為正確的類(lèi)型
- var right1 = numbers.Take((int)number);
- // 2. 用調(diào)用靜態(tài)方法的方式來(lái)進(jìn)行調(diào)用
- var right2 = Enumerable.Take(numbers, number);
.2 委托與動(dòng)態(tài)類(lèi)型不能隱式轉(zhuǎn)換的限制
如果需要將Lambda表達(dá)式,匿名方法轉(zhuǎn)化為動(dòng)態(tài)類(lèi)型時(shí),此時(shí)編譯器必須知道委托的確切類(lèi)型,不能不加強(qiáng)制轉(zhuǎn)化就把他們?cè)O(shè)置為Delegae或object變量,此時(shí)不同string,int類(lèi)型(因?yàn)榍懊鎖nt,string類(lèi)型可以隱式轉(zhuǎn)化為動(dòng)態(tài)類(lèi)型,編譯器此時(shí)會(huì)把他們?cè)O(shè)置為object類(lèi)型。但是匿名方法和Lambda表達(dá)式不能隱式轉(zhuǎn)化為動(dòng)態(tài)類(lèi)型),如果需要完成這樣的轉(zhuǎn)換,此時(shí)必須強(qiáng)制指定委托的類(lèi)型,下面是一個(gè)演示例子:
- dynamic lambdarestrict = x => x + 1; // 編譯時(shí)錯(cuò)誤
- // 解決方案
- dynamic rightlambda =(Func<int,int>)( x=>x+1);
- dynamic methodrestrict = Console.WriteLine; // 編譯時(shí)錯(cuò)誤
- // 解決方案
- dynamic rightmethod =(Action<string>)Console.WriteLine;
5.3 動(dòng)態(tài)類(lèi)型不能調(diào)用構(gòu)造函數(shù)和靜態(tài)方法的限制——即不能對(duì)動(dòng)態(tài)類(lèi)型調(diào)用構(gòu)造函數(shù)或靜態(tài)方法,因?yàn)榇藭r(shí)編譯器無(wú)法指定具體的類(lèi)型。
- dynamic s = new dynamic();
5.4 類(lèi)型聲明和泛型類(lèi)型參數(shù)
不能聲明一個(gè)基類(lèi)為dynamic的類(lèi)型,也不能將dynamic用于類(lèi)型參數(shù)的約束,或作為類(lèi)型所實(shí)現(xiàn)的接口的一部分,下面看一些具體的例子來(lái)加深概念的理解:
- // 基類(lèi)不能為dynamic 類(lèi)型
- class DynamicBaseType : dynamic
- {
- }
- // dynamic類(lèi)型不能為類(lèi)型參數(shù)的約束
- class DynamicTypeConstrain<T> where T : dynamic
- {
- }
- // 不能作為所實(shí)現(xiàn)接口的一部分
- class DynamicInterface : IEnumerable<dynamic>
- {
- }
六、實(shí)現(xiàn)動(dòng)態(tài)的行為
介紹了這么動(dòng)態(tài)類(lèi)型,是不是大家都迫不及待地想知道如果讓自己的類(lèi)型具有動(dòng)態(tài)的行為呢? 然而實(shí)現(xiàn)動(dòng)態(tài)行為有三種方式:
下面就從最簡(jiǎn)單的方式:
6.1 使用ExpandObject來(lái)實(shí)現(xiàn)動(dòng)態(tài)的行為
- using System;
- // 引入額外的命名空間
- using System.Dynamic;
- namespace 自定義動(dòng)態(tài)類(lèi)型
- {
- class Program
- {
- static void Main(string[] args)
- {
- dynamic expand = new ExpandoObject();
- // 動(dòng)態(tài)為expand類(lèi)型綁定屬性
- expand.Name = "Learning Hard";
- expand.Age = 24;
- // 動(dòng)態(tài)為expand類(lèi)型綁定方法
- expand.Addmethod = (Func<int, int>)(x => x + 1);
- // 訪(fǎng)問(wèn)expand類(lèi)型的屬性和方法
- Console.WriteLine("expand類(lèi)型的姓名為:"+expand.Name+" 年齡為: "+expand.Age);
- Console.WriteLine("調(diào)用expand類(lèi)型的動(dòng)態(tài)綁定的方法:" +expand.Addmethod(5));
- Console.Read();
- }
- }
- }
運(yùn)行的結(jié)果和預(yù)期的一樣,運(yùn)行結(jié)果為:
6.2 使用DynamicObject來(lái)實(shí)現(xiàn)動(dòng)態(tài)行為
- static void Main(string[] args)
- {
- dynamic dynamicobj = new DynamicType();
- dynamicobj.CallMethod();
- dynamicobj.Name = "Learning Hard";
- dynamicobj.Age = "24";
- Console.Read();
- }
- class DynamicType : DynamicObject
- {
- // 重寫(xiě)方法,
- // TryXXX方法表示對(duì)對(duì)象的動(dòng)態(tài)調(diào)用
- public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
- {
- Console.WriteLine(binder.Name +" 方法正在被調(diào)用");
- result = null;
- return true;
- }
- public override bool TrySetMember(SetMemberBinder binder, object value)
- {
- Console.WriteLine(binder.Name + " 屬性被設(shè)置," + "設(shè)置的值為: " + value);
- return true;
- }
- }
運(yùn)行結(jié)果為:
6.3 實(shí)現(xiàn)IDynamicMetaObjectProvider接口來(lái)實(shí)現(xiàn)動(dòng)態(tài)行為
由于Dynamic類(lèi)型在運(yùn)行時(shí)來(lái)動(dòng)態(tài)創(chuàng)建對(duì)象的,所以對(duì)該類(lèi)型的每個(gè)成員的訪(fǎng)問(wèn)都會(huì)調(diào)用GetMetaObject方法來(lái)獲得動(dòng)態(tài)對(duì)象,然后通過(guò)這個(gè)動(dòng)態(tài)對(duì)象來(lái)進(jìn)行調(diào)用,所以實(shí)現(xiàn)IDynamicMetaObjectProvider接口,需要實(shí)現(xiàn)一個(gè)GetMetaObject方法來(lái)返回DynamicMetaObject對(duì)象,演示代碼如下:
- static void Main(string[] args)
- {
- dynamic dynamicobj2 = new DynamicType2();
- dynamicobj2.Call();
- Console.Read();
- }
- public class DynamicType2 : IDynamicMetaObjectProvider
- {
- public DynamicMetaObject GetMetaObject(Expression parameter)
- {
- Console.WriteLine("開(kāi)始獲得元數(shù)據(jù)......");
- return new Metadynamic(parameter,this);
- }
- }
- // 自定義Metadynamic類(lèi)
- public class Metadynamic : DynamicMetaObject
- {
- internal Metadynamic(Expression expression, DynamicType2 value)
- : base(expression, BindingRestrictions.Empty, value)
- {
- }
- // 重寫(xiě)響應(yīng)成員調(diào)用方法
- public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
- {
- // 獲得真正的對(duì)象
- DynamicType2 target = (DynamicType2)base.Value;
- Expression self = Expression.Convert(base.Expression, typeof(DynamicType2));
- var restrictions = BindingRestrictions.GetInstanceRestriction(self, target);
- // 輸出綁定方法名
- Console.WriteLine(binder.Name + " 方法被調(diào)用了");
- return new DynamicMetaObject(self, restrictions);
- }
- }
運(yùn)行結(jié)果為:
七、總結(jié)
講到這里動(dòng)態(tài)類(lèi)型的介紹就已經(jīng)介紹完了,本專(zhuān)題差不多涵蓋了動(dòng)態(tài)類(lèi)型中所有內(nèi)容,希望通過(guò)本專(zhuān)題大家能夠?qū)# 4.0中提出來(lái)的動(dòng)態(tài)類(lèi)型特性可以有進(jìn)一步的了解,并且本專(zhuān)題也是這個(gè)系列中的最后一篇文章了,到這里C#基礎(chǔ)知識(shí)系列也就結(jié)束了,后面我會(huì)整理出這個(gè)系列文章的一個(gè)索引,從而方便大家收藏,然而C#4中對(duì)COM互操作性也有很大的改善,關(guān)于互操作的內(nèi)容將會(huì)在后面一個(gè)系列文章中和大家分享下我的學(xué)習(xí)體會(huì)。
當(dāng)前題目:[C#基礎(chǔ)知識(shí)系列]專(zhuān)題十七:深入理解動(dòng)態(tài)類(lèi)型
標(biāo)題URL:http://www.rwnh.cn/article6/jgjjig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、微信小程序、標(biāo)簽優(yōu)化、網(wǎng)站內(nèi)鏈、App開(kāi)發(fā)、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)