C#中的反射解析及使用(轉)

原文:https://cloud.tencent.com/developer/article/1129356
一、對C#反射機制的理解
二、概念理解後,必須找到方法去完成,給出管理的主要語法
三、最終給出實用的例子,反射出來dll中的方法編程

參考: C#反射,MSDN編程指南c#

反射是一個程序集發現及運行的過程,經過反射能夠獲得.exe或.dll等程序集內部的信息。使用反射能夠看到一個程序集內部的接口、類、方法、字段、屬性、特性等等信息。在System.Reflection命名空間內包含多個反射經常使用的類,下面表格列出了經常使用的幾個類。
類型 做用
Assembly 經過此類能夠加載操縱一個程序集,並獲取程序集內部信息
EventInfo 該類保存給定的事件信息
FieldInfo 該類保存給定的字段信息
MethodInfo 該類保存給定的方法信息
MemberInfo 該類是一個基類,它定義了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多個公用行爲
Module 該類可使你能訪問多個程序集中的給定模塊
ParameterInfo 該類保存給定的參數信息      
PropertyInfo 該類保存給定的屬性信息設計

1、System.Reflection.Assembly類
經過Assembly能夠動態加載程序集,並查看程序集的內部信息,其中最經常使用的就是Load()這個方法。
Assembly assembly=Assembly.Load("MyAssembly");
利用Assembly的object CreateInstance(string) 方法能夠反射建立一個對象,參數0爲類名。
2、System.Type類
Type是最經常使用到的類,經過Type能夠獲得一個類的內部信息,也能夠經過它反射建立一個對象。通常有三個經常使用的方法可獲得Type對象。code

//利用typeof() 獲得Type對象
Type type=typeof(Example);
//利用System.Object.GetType() 獲得Type對象
Example example=new Example();
Type type=example.GetType();
//利用System.Type.GetType() 獲得Type對象
Type type=Type.GetType("MyAssembly.Example",false,true);

注意參數0是類名,參數1表示若找不到對應類時是否拋出異常,參數1表示類名是否區分大小寫
例子:
咱們最多見的是利用反射與Activator結合來建立對象。對象

Assembly assembly= Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);

3、反射方法
1.經過 System.Reflection.MethodInfo能查找到類裏面的方法接口

Type type=typeof(Example);
MethodInfo[] listMethodInfo=type.GetMethods();
foreach(MethodInfo methodInfo in listMethodInfo)
Cosole.WriteLine("Method name is "+methodInfo.Name);

2.咱們也能經過反射方法執行類裏面的方法2.咱們也能經過反射方法執行類裏面的方法事件

Assembly assembly= Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);
MethodInfo methodInfo=type.GetMethod("Hello World");  //根據方法名獲取MethodInfo對象
methodInfo.Invoke(obj,null);  //參數1類型爲object[],表明Hello World方法的對應參數,輸入值爲null表明沒有參數

4、反射屬性
1.經過 System.Reflection.PropertyInfo 能查找到類裏面的屬性
經常使用的方法有GetValue(object,object[]) 獲取屬性值和 SetValue(object,object,object[]) 設置屬性值ip

Type type=typeof(Example);
PropertyInfo[] listPropertyInfo=type.GetProperties();
foreach(PropertyInfo propertyInfo in listPropertyInfo)
Cosole.WriteLine("Property name is "+ propertyInfo.Name);

2.咱們也能夠經過如下方法設置或者獲取一個對象的屬性值2.咱們也能夠經過如下方法設置或者獲取一個對象的屬性值get

Assembly assembly=Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);
PropertyInfo propertyInfo=obj.GetProperty("Name");    //獲取Name屬性對象
var name=propertyInfo.GetValue(obj,null);                //獲取Name屬性的值
PropertyInfo propertyInfo2=obj.GetProperty("Age");     //獲取Age屬性對象
propertyInfo.SetValue(obj,34,null);                              //把Age屬性設置爲34

5、反射字段
經過 System.Reflection.FieldInfo 能查找到類裏面的字段
它包括有兩個經常使用方法SetValue(object ,object )和GetValue(object) 由於使用方法與反射屬性很是類似,在此再也不多做介紹string

6、反射特性
經過System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一個類裏面的特性,如下例子能夠反射出一個類的全部特性

Type type=typeof("Example");
object[] typeAttributes=type.GetCustomAttributes(false);       //獲取Example類的特性
foreach(object attribute in typeAttributes)
Console.WriteLine("Attributes description is "+attribute.ToString());

經過下面例子,能夠獲取Example類Name屬性的全部特性經過下面例子,能夠獲取Example類Name屬性的全部特性

public class Example
 {
      [DataMemberAttribute]
      publics string Name
      {get;set;}
      ..................
 } 
Type type = typeof(Example);        
PropertyInfo propertyInfo=type.GetProperty("Name");    //獲取Example類的Name屬性
foreach (object attribute in propertyInfo.GetCustomAttributes(false))        //遍歷Name屬性的全部特性
Console.WriteLine(「Property attribute: "+attribute.ToString());

總結:

Assembly.Load()方法,Assembly.LoadFrom()方法,Assembly.LoadFile()方法的區別
在C#中,咱們要使用反射,首先要搞清楚如下命名空間中幾個類的關係:
System.Reflection命名空間
(1) AppDomain:應用程序域,能夠將其理解爲一組程序集的邏輯容器
(2) Assembly:程序集類
(3) Module:模塊類
(4) Type:使用反射獲得類型信息的最核心的類
他們之間是一種從屬關係,也就是說,一個AppDomain能夠包含N個Assembly,一個Assembly能夠包含N個Module,而一個Module能夠包含N個Type.

1,Assembly.Load()
這個方法經過程序集的長名稱(包括程序集名,版本信息,語言文化,公鑰標記)來加載程序集的,會加載此程序集引用的其餘程序集,通常狀況下都應該優先使用 這個方法,他的執行效率比LoadFrom要高不少,並且不會形成重複加載的問題(緣由在第2點上說明)
使用這個方法的時候, CLR會應用必定的策略來查找程序集,實際上CLR按以下的順序來定位程序集:
⑴若是程序集有強名稱,在首先在全局程序集緩(GAC)中查找程序集。
⑵若是程序集的強名稱沒有正確指定或GAC中找不到,那麼經過配置文件中的 元素指定的URL來查找
⑶若是沒有指定強名稱或是在GAC中找不到,CLR會探測特定的文件夾:
假設你的應用程序目錄是C:\AppDir, 元素中的privatePath指定了一個路徑Path1,你要定位的程序集是AssemblyName.dll則CLR將按照以下順序定位程序集 C:\AppDir\AssemblyName.dll C:\AppDir\AssemblyName\AssemblyName.dll C:\AppDir\Path1\AssemblyName.dll C:\AppDir\Path1\AssemblyName\AssemblyName.dll 若是以上方法不能找到程序集,會發生編譯錯誤,若是是動態加載程序集,會在運行時拋出異常! 2,Assembly.LoadFrom() 這個方法從指定的路徑來加載程序集,實際上這個方法被調用的時候,CLR會打開這個文件,獲取其中的程序集版本,語言文化,公鑰標記等信息,把他們傳遞給 Load方法,接着,Load方法採用上面的策略來查找程序集。若是找到了程序集,會和LoadFrom方法中指定的路徑作比較,若是路徑相同,該程序集 會被認爲是應用程序的一部分,若是路徑不一樣或Load方法沒有找到程序集,那該程序集只是被做爲一個"數據文件"來加載,不會被認爲是應用程序的一部分。 這就是在第1點中提到的Load方法比LoadFrom方法的執行效率高的緣由。另外,因爲可能把程序集做爲"數據文件"來加載,因此使用 LoadFrom從不一樣路徑加載相同程序集的時候會致使重複加載。固然這個方法會加載此程序集引用的其餘程序集。 3,Assembly.LoadFile() 這個方法是從指定的文件來加載程序集,和上面方法的不一樣之處是這個方法不會加載此程序集引用的其餘程序集! 結論:通常你們應該優先選擇Load方法來加載程序集,若是遇到須要使用LoadFrom方法的時候,最好改變設計而用Load方法來代替! 另:Assembly.LoadFile 與 Assembly.LoadFrom的區別 一、Assembly.LoadFile只載入相應的dll文件,好比Assembly.LoadFile("abc.dll"),則載入abc.dll,假如abc.dll中引用了def.dll的話,def.dll並不會被載入。 Assembly.LoadFrom則不同,它會載入dll文件及其引用的其餘dll,好比上面的例子,def.dll也會被載入。 二、用Assembly.LoadFrom載入一個Assembly時,會先檢查前面是否已經載入過相同名字的Assembly,好比abc.dll有兩個版本(版本1在目錄1下,版本2放在目錄2下),程序一開始時載入了版本1,當使用Assembly.LoadFrom("2\abc.dll")載入版本2時,不能載入,而是返回版本1.Assembly.LoadFile的話則不會作這樣的檢查,好比上面的例子換成Assembly.LoadFile的話,則能正確載入版本2. LoadFile:加載指定路徑上的程序集文件的內容。LoadFrom: 根據程序集的文件名加載程序集文件的內容。 區別: LoadFile 方法用來來加載和檢查具備相同標識但位於不一樣路徑中的程序集。但不會加載程序的依賴項。 LoadFrom 不能用於加載標識相同但路徑不一樣的程序集。

相關文章
相關標籤/搜索