生活随笔
收集整理的這篇文章主要介紹了
再议C#方法中的反射方式和委托方式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
再議C#方法中的反射方式和委托方式
我們將要談到的是C#方法中的反射方式和委托方式,文中還將給出具體代碼,以方便大家測試和實踐。
AD:
在開發過程中對靜態方法的調用是通過類型名后面加個點而后是調用方法的名稱,對類型實例方法的調用是通過new一個對象,而后點加方法名稱,這是最熟悉不過的兩種方式。還可以通過讀取CLR元數據,利用反射進行方法調用。在利用反射方式調用方法時,最重要的兩個類是System.Type和System.Reflection.MethodInfo。用MethodInfo類型的Invoke方法調用方法,必須傳入目標對象實例的引用。如下:
public class Calculate ?{ ? ? private?intAdd(int leftNum,?int rightNum) ? { ?return leftNum?+?rightNum; ?} ? } ?classProgram ?{ ? static voidMain(string[]?args) ? { ? ? ? ? MethodInfo method?=?typeof(Calculate).GetMethod("Add",?BindingFlags.Public ? |?BindingFlags.NonPublic ?|BindingFlags.Instance); ? if(method?==?null)?return? ? object[]?paras?={?10,?20?}; ? ? objectresult?=?method.Invoke(new Calculate(),?paras); ?Console.WriteLine(result); ?Console.ReadLine(); ?} ?}?委托方式
任何對象都可以調用委托,只要方法返回值以及方法簽名和委托聲明一樣就行。
通過閱讀CLR源代碼,整理了委托類的重要字段和幾個常用方法,自定義的委托類型都派生于MulticastDelegate。
public abstract class Delegate:?ICloneable,ISerializable ?{ ? ? internalObject_target; ? ? internalIntPtr_methodPtr; ? ? protected Delegate(Objecttarget,?Stringmethod) ?{ ? ? } ?public static Delegate CreateDelegate(Typetype,?Objecttarget,?Stringmethod) ?{ ? ? } ?public static Delegate CreateDelegate(Typetype,?Typetarget,?Stringmethod) ?{ ? ? } ?public static Delegate Combine(paramsDelegate[]?delegates)?{} ?public static Delegate Combine(Delegatea,?Delegateb)?{} ?public static Delegate Remove(Delegatesource,?Delegatevalue){} ?} ?public abstract class MulticastDelegate:?Delegate ?{ ?private Object _invocationList; ? protected MulticastDelegate(Objecttarget,?Stringmethod)?:?base(target,?method)?{?} ? protectedMulticastDelegate(Typetarget,?Stringmethod):?base(target,?method)?{?} ? }?從源代碼可以看出Delegate類提供了幾個重載的靜態方法CreateDelegate,方法返回值是Delegate類型。如果是實例方法則把對象引用傳遞給它,如是靜態方法則傳入對象類型。
publicdelegateintDelegateCaculate(inta,intb); ?publicclassCaculate ?{ ?publicintAdd(intnum1,?intnum2) ?{ ?returnnum1?+?num2; ?} ?publicstaticintSubtract(intnum1,?intnum2) ?{ ? returnnum2?-?num1; ?} ?} ?classProgram ? { ? staticvoidMain(string[]?args) ? { ?Caculatecaculate?=?newCaculate(); ? TypetypeCaculate?=?typeof(Caculate); ? TypetypeDelegate?=?typeof(DelegateCaculate); ? DelegateCaculateadd?=?(DelegateCaculate)Delegate.CreateDelegate(typeDelegate,?caculate,?"Add"); ? DelegateCaculatesubtract?=?(DelegateCaculate)Delegate.CreateDelegate(typeDelegate,?typeCaculate,?"Subtract"); ? Console.WriteLine("add:"+?add(10,?20)); ? Console.WriteLine("subtract:"+?subtract(10,?20)); ? Console.ReadLine(); ?} ?}?CreateDelegate需要通過遍歷元數據來獲取方法句柄。C#語法提供了更便利的方法來調用委托,可以簡單通過類型名或者對象名來限定方法,而且不需要通過遍歷元數據,C#編譯器使用底層CIL的ldftn或許ldvirtftn操作符獲取方法地址,相對來說要比CreateDelegate快的多了。上面的Main方法可以改寫為
staticvoidMain(string[]?args) ?{ ?DelegateCaculateadd?=?newDelegateCaculate(newCaculate().Add); ?DelegateCaculatesubtract?=?newDelegateCaculate(Caculate.Subtract); ? Console.WriteLine("add:"+?add(10,?20)); ? Console.WriteLine("subtract:"+?subtract(10,?20)); ? Console.ReadLine(); ?}?可以將多個委托對象放到委托對象數組中,一旦對其調用,CLR將遍歷委托數組,對其逐一調用。
publicdelegatevoidDelegateCaculate(inta,intb); ?publicclassCaculate ?{ ?publicstaticvoidAdd(intnum1,?intnum2) ?{ ?Console.WriteLine((num1+?num2)); ?} ?publicstaticvoidSubtract(intnum1,?intnum2) ?{ ?Console.WriteLine((num2-?num1)); ?} ?} ?classProgram ?{ ? staticvoidMain(string[]?args) ? { ?DelegateArray(newDelegateCaculate(Caculate.Add),?newDelegateCaculate(Caculate.Subtract)); ?Console.ReadLine(); ?} ?staticvoidDelegateArray(DelegateCaculatea,?DelegateCaculateb) ?{ ? DelegateCaculatedelChain?=?null? delChain?=?(DelegateCaculate)Delegate.Combine(delChain,?a); ?delChain?=?(DelegateCaculate)Delegate.Combine(delChain,?b); ?delChain(10,?20); ?} ?}?C#提供了更便捷的語法把委托對象添加到委托數組內,可以這樣修改上面的DelegateArray方法,
staticvoidDelegateArray(DelegateCaculatea,?DelegateCaculateb) ? { ? DelegateCaculatedelChain?=?null? delChain?+=?a; ?delChain+=b; ?delChain(10,?20); ?}?當執行(DelegateCaculate)Delegate.Combine(delChain, a)時,因為委托數組中只有一個a對象,所以delChain也只是簡單的指向a。示意圖如下
當執行(DelegateCaculate)Delegate.Combine(delChain, b)是,因為委托數組已經有兩個對象了,這時會生成一個新的MulticastDelegate對象讓delChain指向它,而_invocationList指向一個委托數組對象,示意圖如下
如果還有委托對象加入,將會再次生成一個新的MulticastDelegate對象讓delChain指向這個新對象,原來的對象則等待垃圾回收器進行回收,這點可以查看CLR源代碼,每添加一個委托對象就調用一次方法NewMulticastDelegate,這個方法返回值是MulticastDelegate。
委托與接口
接口與委托都擁有調用特定方法的能力,所以他們在這點很相像。但是接口需要目標方法的類型聲明必須與該接口兼容,而委托可以被任何類型調用,只要該類型的目標方法簽名和委托簽名匹配即可。
那么何時用委托,何時用接口呢,msdn 總結的非常好,我就直接給粘貼過來了,
委托在以下情況很有用:
1、 調用單個方法。
2、 一個類希望有方法規范的多個實現。
3、 希望允許靜態方法實現規范。
4、 希望類似事件的設計模式。
5、 調用方不需要知道或獲得實現與委托簽名匹配的方法的對象。
6、 實現的提供程序希望只對少數選擇組件“分發”規范實現。
7、 需要方法的組合。
接口在以下情況很有用:
1、 規范定義一組相關方法。
2、 類通常只實現規范一次。
3、 接口的調用方希望轉換為接口類型或從接口類型轉換,以獲得其他接口或類。
原文鏈接:http://www.cnblogs.com/qiuwuyu/archive/2011/08/29/2157230.html
本文轉自左正博客園博客,原文鏈接:http://www.cnblogs.com/soundcode/archive/2011/10/14/2211409.html,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的再议C#方法中的反射方式和委托方式的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。