最近一直都在看關(guān)于程序集加載和反射方面的資料, 所以在這里把我所學(xué)習(xí)到的東西記錄下來(lái),方便自己以后復(fù)習(xí),也給園子里面不懂的朋友參考。 一、程序集的加載JIT編譯器器將IL代碼編譯成本地代碼時(shí), 會(huì)查看IL代碼中引用了哪些類(lèi)型。在運(yùn)行過(guò)程中,JIT編譯器利用程序集的TypeRef和AssemblyRef元數(shù)據(jù)表來(lái)確定哪一個(gè)程序集定義了所引用的類(lèi)型,然后JIT編譯器將對(duì)應(yīng)程序集加載到AppDomain中,在內(nèi)部,CLR使用System.Reflection.Assembly類(lèi)的靜態(tài)方法Load來(lái)嘗試加載一個(gè)程序集。然而如果我們想動(dòng)態(tài)加載一個(gè)程序集時(shí),可以使用Assembly的Load方法來(lái)動(dòng)態(tài)加載程序集,其中Assembly類(lèi)中還提供了其他的加載程序集方法,有LoadFrom(string path), LoadFile(stringassemblyFile)等,具體方法的使用和解釋可以參照MSDN中的介紹:http://msdn.microsoft.com/zh-cn/library/xbe1wdx9
二、反射機(jī)制.net中反射在運(yùn)行中過(guò)程中解析程序集中的元數(shù)據(jù),獲得類(lèi)型中的成員(包括字段、構(gòu)造器、方法、屬性、事件等)信息。 動(dòng)態(tài)加載一個(gè)程序集并獲得類(lèi)型中的成員把下面的類(lèi)放在一個(gè)類(lèi)庫(kù)工程中,并編譯生成程序集(例如為ClassLibrary1.dll,假設(shè)把dll放在D盤(pán)根目錄下面) ![]() ![]() 1 public class ReflectTestClass 2 { 3 public string name; 4 public int age; 5 public string Name 6 { 7 get { return name; } 8 set { name = value; } 9 } 10 11 public int Age 12 { 13 get { return age; } 14 set { age = value; } 15 } 16 17 /// <summary> 18 /// No Paramter Constructor 19 /// </summary> 20 public ReflectTestClass() 21 { 22 } 23 24 /// <summary> 25 /// Constructor with Parameter 26 /// </summary> 27 /// <param name="name"></param> 28 /// <param name="age"></param> 29 public ReflectTestClass(string names,int ages) 30 { 31 this.name = names; 32 this.age = ages; 33 } 34 35 public string writeString(string name) 36 { 37 return "Welcome " + name; 38 } 39 40 public static string WriteName(string name) 41 { 42 return "Welcome "+name +" Come here"; 43 } 44 45 public string WirteNopara() 46 { 47 return "The method is no parameter "; 48 } 49 } 然后建立一個(gè)控制臺(tái)程序用來(lái)動(dòng)態(tài)加載上面生成的程序集和輸出類(lèi)型中的成員,代碼中有詳細(xì)的介紹。 class Program { static void Main(string[] args) { Assembly ass; Type[] types; Type typeA; object obj; try { // 從本地中 加載程序集 然后從程序集中通過(guò)反射獲得類(lèi)型的信息的,并且調(diào)用方法 ass = Assembly.LoadFrom(@"D:\ClassLibrary1.dll"); types = ass.GetTypes(); foreach (Type type in types) { Console.WriteLine("Class Name is " + type.FullName); Console.WriteLine("Constructor Information"); Console.WriteLine("-----------------------"); // 獲取類(lèi)型的結(jié)構(gòu)信息 ConstructorInfo[] myconstructors = type.GetConstructors(); ShowMessage<ConstructorInfo>(myconstructors); Console.WriteLine("Fields Information"); Console.WriteLine("-----------------------"); // 獲取類(lèi)型的字段信息 FieldInfo[] myfields = type.GetFields(); ShowMessage<FieldInfo>(myfields); Console.WriteLine("All Methods Information"); Console.WriteLine("-----------------------"); // 獲取方法信息 MethodInfo[] myMethodInfo = type.GetMethods(); ShowMessage<MethodInfo>(myMethodInfo); Console.WriteLine("All Properties Information"); Console.WriteLine("-----------------------"); // 獲取屬性信息 PropertyInfo[] myproperties = type.GetProperties(); ShowMessage<PropertyInfo>(myproperties); } // 用命名空間+類(lèi)名獲取類(lèi)型 typeA = ass.GetType("ClassLibrary1.ReflectTestClass"); // 獲得方法名稱(chēng) MethodInfo method = typeA.GetMethod("writeString"); // 創(chuàng)建實(shí)例 obj = ass.CreateInstance("ClassLibrary1.ReflectTestClass"); string result = (String)method.Invoke(obj,new string[] {"Tom"}); Console.WriteLine("Invoke Method With Parameter"); Console.WriteLine("-----------------------"); Console.WriteLine(result); Console.WriteLine("-----------------------"); Console.WriteLine(); method = typeA.GetMethod("WriteName"); result = (string)method.Invoke(null,new string[] {"Tom"}); Console.WriteLine("Invoke Static Method with Parameter"); Console.WriteLine("-----------------------"); Console.WriteLine(result); Console.WriteLine("-----------------------"); Console.WriteLine(); method = typeA.GetMethod("WirteNopara"); Console.WriteLine("Invoke Method with NOParameter"); result = (string)method.Invoke(obj, null); Console.WriteLine("-----------------------"); Console.WriteLine(result); Console.WriteLine("-----------------------"); } catch(FileNotFoundException ex) { Console.WriteLine(ex.Message); } Console.ReadLine(); } /// <summary> /// 顯示數(shù)組信息 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="os"></param> public static void ShowMessage<T>(T[] array) { foreach(T member in array) { Console.WriteLine(member.ToString()); } Console.WriteLine("-----------------------"); Console.WriteLine(); } }
可以調(diào)用Type的GetMembers,GetFields,GetMethods,GetProperties或者GetEvenents方法來(lái)查詢(xún)一個(gè)類(lèi)型的成員。在調(diào)用上面的任何一個(gè)方法時(shí),都可以傳遞System.Reflection.BindingFlags枚舉類(lèi)型的一個(gè)實(shí)例,使用這個(gè)枚舉類(lèi)型目的是對(duì)這些方法返回的成員進(jìn)行篩選。對(duì)于這個(gè)枚舉類(lèi)型中成員的信息可以參考MSDN:http://msdn.microsoft.com/zh-cn/library/system.reflection.bindingflags(v=VS.80).aspx 注意:在返回一個(gè)成員集合的所有方法中, 都有一個(gè)不獲取任何實(shí)參的重載版本。如果不傳遞BindingFlags實(shí)參,所有這些方法都返回公共成員,默認(rèn)設(shè)置為BindingFlags.Public|BindingFlags.Instance|BindingFlags.Static. (如果指定Public或NonPublic,那么必須同時(shí)指定Instance,否則不返回成員)。 |
|
來(lái)自: 昵稱(chēng)10504424 > 《C#》