反射用于在程式運作過程中,擷取類裡面的資訊或發現程式集并運作的一個過程。通過反射可以獲得.dll和.exe字尾的程式集裡面的資訊。使用反射可以看到一個程式集内部的類,接口,字段,屬性,方法,特性等資訊。
首先就是擷取Tyoe對象的來源不同:
三者的差別在于typeof()和Type.GetType()是從一個類中擷取對象,而Object.GetType()是從一個類的執行個體獲得對象。
而前兩者的差別在于:
隻有typeof()是運算符。
Type.GetType()是執行個體方法。
Object.GetType()是基類System.Object的方法(無參數,在Type類、Assembly類、Module類中都有這個無參方法),執行個體方法。
Assembly.GetType() 、Module.GetType()、Type.Get()都是各自對象的執行個體方法。
在System.Reflection命名空間内包含多個反射常用的類,下面表格列出了常用的幾個類。
類型
作用
Assembly
通過此類可以加載操縱一個程式集,并擷取程式集内部資訊
EventInfo
該類儲存給定的事件資訊
FieldInfo
該類儲存給定的字段資訊
MethodInfo
該類儲存給定的方法資訊
MemberInfo
該類是一個基類,它定義了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多個公用行為
Module
該類可以使你能通路多個程式集中的給定子產品
ParameterInfo
該類儲存給定的參數資訊
PropertyInfo
該類儲存給定的屬性資訊
通過Assembly可以動态加載程式集,并檢視程式集的内部資訊,其中最常用的就是Load()這個方法。
注意在Assembly裡面的加載程式集有3個方法,分别是Load、LoadFrom和LoadFile。這3個方法有什麼異同呢?
1、如果你引用了命名空間,那麼就直接Load()方法,參數裡面寫上命名空間+類名就可以加載了。
2、如果僅僅知道一個dll檔案的那麼就要用LoadFrom()方法了,參數裡面直接填寫完整的路徑。
LoadFrom 方法具有以下缺點。請考慮改用 Load。
-如果已加載一個具有相同辨別的程式集,則即使指定了不同的路徑,LoadFrom 仍傳回已加載的程式集。
-如果用 LoadFrom
加載一個程式集,随後加載上下文中的一個程式集嘗試加載具有相同顯示名稱的程式集,則加載嘗試将失敗。對程式集進行反序列化時,可能發生這種情況。
總結: LoadFrom隻能用于加載不同辨別的程式集, 也就是唯一的程式集, 不能用于加載辨別相同但路徑不同的程式集。
3、LoadFile (加載指定路徑上的程式集檔案的内容。)
這個方法是從指定的檔案來加載程式集,它是調用外部的API實作的加載方式,和上面Load,LoadFrom方法的不同之處是這個方法不會加載此程式集引用的其他程式集,也就是不會加載程式的依賴項。而同時也是不能加載相同辨別的程式集的。
利用Assembly的object CreateInstance(string)方法可以反射建立一個對象,參數0為類名。
Type是最常用到的類,它一般用于裝載反射得到的類對象,通過Type可以得到一個類的内部資訊,也可以通過它反射建立一個對象。一般有三個常用的方法可以得到Type對象。
1.利用typeof()得到Type對象
2.利用System.Object.GetType()得到Type對象
3.利用System.Type.GetType()得到Type對象
示例:
1.通過 Type.GetMethods()能查找到類裡面的方法
代碼示例:
輸出結果如下:
留意到裡面所有的方法,包括繼承來的都列出來了。另外可以留意到,屬性的讀取設定,在根本上也是一個方法。
調用反射得到的方法使用Invoke方法(),示例如下:
1、通過System.Reflection.Property能查找到類裡面的屬性
常用的方法有GetValue(object,object[])擷取屬性值和SetValue(object,object,object[])設定屬性值
代碼示例:
輸出結果如下:
2、另外還可以通過PropertyInfo對象的GetValue和SetValue方法讀取和設定建立出來的對象的屬性值
下面給出一個方法與屬性的綜合示例:
Person類的代碼如下:
2、根據屬性的類型設定屬性的值:
我們有可能會一次過設定很多屬性的值,而這些屬性裡面可能有字元串類型、整型等等。是以,我們需要動态設定,這是需要根據屬性的類型設定屬性的值。
輸出如下:
如果不根據類型來轉換,則報如下錯誤:
通過 System.Reflection.FieldInfo 能查找到類裡面的字段
它包括有兩個常用方法SetValue(object ,object )和GetValue(object)
因為使用方法與反射屬性非常相似。
通過System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一個類裡面的特性。
利用反射實作的簡單工廠模式的多資料庫系統執行個體:
App.Config配置檔案
主程式代碼:
2、不引用命名空間根據路徑運作dll裡的方法示例
Person類代碼:
3、獲得List<T>中的T類型:
當然,如果List<T>是你定義的泛型,那麼直接typeof(T)更加簡單。