C#反射的入門(mén)學(xué)習首先要明白C#反射提供了封裝程序集、模塊和類(lèi)型的對象等等。那么這樣可以使用反射動(dòng)態(tài)創(chuàng )建類(lèi)型的實(shí)例,將類(lèi)型綁定到現有對象,或從現有對象獲取類(lèi)型并調用其方法或訪(fǎng)問(wèn)其字段和屬性。如果代碼中使用了屬性,可以利用反射對它們進(jìn)行訪(fǎng)問(wèn)。
MSDN描述:
反射通常具有以下用途:
使用 Assembly 定義和加載程序集,加載在程序集清單中列出的模塊,以及從此程序集中查找類(lèi)型并創(chuàng )建該類(lèi)型的實(shí)例。
使用 Module 發(fā)現以下信息:包含模塊的程序集以及模塊中的類(lèi)等。您還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。
使用 ConstructorInfo 發(fā)現以下信息:構造函數的名稱(chēng)、參數、訪(fǎng)問(wèn)修飾符(如 public 或 private)和實(shí)現詳細信息(如 abstract 或 virtual)等。使用 Type 的 GetConstructors 或 GetConstructor 方法來(lái)調用特定的構造函數。
使用 MethodInfo 發(fā)現以下信息:方法的名稱(chēng)、返回類(lèi)型、參數、訪(fǎng)問(wèn)修飾符(如 public 或 private)和實(shí)現詳細信息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法來(lái)調用特定的方法。
使用 FieldInfo 發(fā)現以下信息:字段的名稱(chēng)、訪(fǎng)問(wèn)修飾符(如 public 或 private)和實(shí)現詳細信息(如 static)等;并獲取或設置字段值。
使用 EventInfo 發(fā)現以下信息:事件的名稱(chēng)、事件處理程序數據類(lèi)型、自定義屬性、聲明類(lèi)型和反射類(lèi)型等;并添加或移除事件處理程序。
使用 PropertyInfo 發(fā)現以下信息:屬性的名稱(chēng)、數據類(lèi)型、聲明類(lèi)型、反射類(lèi)型和只讀或可寫(xiě)狀態(tài)等;并獲取或設置屬性值。
使用 ParameterInfo 發(fā)現以下信息:參數的名稱(chēng)、數據類(lèi)型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。
當您在一個(gè)應用程序域的僅反射上下文中工作時(shí),請使用 CustomAttributeData 來(lái)了解有關(guān)自定義屬性的信息。使用 CustomAttributeData,您不必創(chuàng )建屬性的實(shí)例就可以檢查它們。
System.Reflection.Emit 命名空間的類(lèi)提供了一種特殊形式的反射,使您能夠在運行時(shí)生成類(lèi)型。
反射也可用于創(chuàng )建稱(chēng)作類(lèi)型瀏覽器的應用程序,它使用戶(hù)能夠選擇類(lèi)型,然后查看有關(guān)選定類(lèi)型的信息。
反射還有其他一些用途。JScript 等語(yǔ)言編譯器使用反射來(lái)構造符號表。System.Runtime.Serialization 命名空間中的類(lèi)使用反射來(lái)訪(fǎng)問(wèn)數據并確定要持久保存的字段。System.Runtime.Remoting 命名空間中的類(lèi)通過(guò)序列化來(lái)間接地使用反射。
一個(gè)最簡(jiǎn)單的C#反射實(shí)例,首先編寫(xiě)類(lèi)庫如下:
using System; namespace ReflectionTest{ public class WriteTest { //public method with parametors public void WriteString(string s, int i) { Console.WriteLine("WriteString:" + s + i.ToString()); } //static method with only one parametor public static void StaticWriteString(string s) { Console.WriteLine("StaticWriteString:" + s); } //static method with no parametor public static void NoneParaWriteString() { Console.WriteLine("NoParaWriteString"); } }}
使用命令行編譯csc /t:library ReflectTest.cs命令進(jìn)行編譯,生成ReflectTest.dll庫文件。
然后進(jìn)行下列程序的編寫(xiě):
using System; using System.Reflection; class TestApp{ public static void Main() { Assembly ass; Type type; Object obj; Object any = new Object(); ass = Assembly.LoadFile(@"@"C:\Users\luogy\Desktop\1\ReflectionTest.dll""); type = ass.GetType("ReflectionTest.WriteTest"); /*example1---------*/ MethodInfo method = type.GetMethod("WriteString"); string test = "test"; int i = 1; Object[] parametors = new Object[] { test, i }; obj = ass.CreateInstance("ReflectionTest.WriteTest"); method.Invoke(obj,//Instance object of the class need to be reflect parametors); //method.Invoke(any, parametors);//RuntimeError: class reference is wrong /*example2----------*/ method = type.GetMethod("StaticWriteString"); method.Invoke(null, new string[] { "test" }); method.Invoke(obj, new string[] { "test" }); method.Invoke(any, new string[] { "test" }); /*example3-----------*/ method = type.GetMethod("NoneParaWriteString"); method.Invoke(null, null);Console.ReadKey(); }}
運行結果:
C#反射學(xué)習時(shí)幾點(diǎn)注意內容:
1.指定類(lèi)庫文件必須使用絕對路徑,不能使用相對路徑(其實(shí)感覺(jué)有點(diǎn)不合理,不太方便)
2.19行,命名空間和類(lèi)的名字必須一起指定
3.在例子1種必須實(shí)例化反射要反射的類(lèi),因為要使用的方法并不是靜態(tài)方法。
4.由于這個(gè)方法有兩個(gè)參數,可以用這種Object的方法指定參數也可以直接寫(xiě)method.Invoke(obj, new Object[] { "test", 1 });
5.在例子2種我們想用的方法是一個(gè)靜態(tài)方法,這時(shí)候Invoke的時(shí)候,對于第一個(gè)參數是無(wú)視的,也就是我們寫(xiě)什么都不會(huì )被調用,即使我們隨便new了一個(gè)any這樣的Object,當然這種寫(xiě)法是不推薦的。但是對應在例子1種我們如果Invoke的時(shí)候用了類(lèi)型不一致的實(shí)例來(lái)做為參數的話(huà),將會(huì )導致一個(gè)運行時(shí)的錯誤。
6.第三個(gè)例子是一個(gè)調用無(wú)參數靜態(tài)方法的例子,這時(shí)候兩個(gè)參數我們都不需要指定,用null就可以了。
再說(shuō)一個(gè)問(wèn)題,如果調用的類(lèi)是靜態(tài)類(lèi)的時(shí)候,需要注意一個(gè)問(wèn)題,肯定我們會(huì )想到一個(gè)問(wèn)題,靜態(tài)類(lèi)是不能實(shí)例化的,這時(shí)候,31行的類(lèi)的實(shí)例化的方法我們就不需要了,直接使用Invoke就可以實(shí)現,否則將會(huì )出現運行時(shí)的錯誤,同樣的道理,第一個(gè)參數將會(huì )被無(wú)視,只要我們傳對了參數就可以了。
C#反射以及C#反射實(shí)例的相關(guān)內容就向你介紹到這里,希望對你了解和學(xué)習C#反射以及C#反射實(shí)例應用有所幫助。
聯(lián)系客服