標籤:不同的 利用 odi data 管理 問題 invoke public 動態載入
1、對C#反射機制的理解
2、概念理解後,必須找到方法去完成,給出管理的主要文法
3、最終給出實用的例子,反射出來dll中的方法
反射是一個程式集發現及啟動並執行過程,通過反射可以得到*.exe或*.dll等程式集內部的資訊。使用反射可以看到一個程式集內部的介面、類、方法、欄位、屬性、特性等等資訊。在System.Reflection命名空間內包含多個反射常用的類,下面表格列出了常用的幾個類。
類型 作用
Assembly 通過此類可以載入操縱一個程式集,並擷取程式集內部資訊
EventInfo 該類儲存給定的事件資訊
FieldInfo 該類儲存給定的欄位資訊
MethodInfo 該類儲存給定的方法資訊
MemberInfo 該類是一個基類,它定義了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多個公用行為
Module 該類可以使你能訪問多個程式集中的給定模組
ParameterInfo 該類儲存給定的參數資訊
PropertyInfo 該類儲存給定的屬性資訊
一、System.Reflection.Assembly類
通過Assembly可以動態載入程式集,並查看程式集的內部資訊,其中最常用的就是Load()這個方法。
Assembly assembly=Assembly.Load("MyAssembly");
利用Assembly的object CreateInstance(string) 方法可以反射建立一個對象,參數0為類名。
二、System.Type類
Type是最常用到的類,通過Type可以得到一個類的內部資訊,也可以通過它反射建立一個對象。一般有三個常用的方法可得到Type對象。
利用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);
三、反射方法
1.通過 System.Reflection.MethodInfo能尋找到類裡面的方法
[csharp]view plaincopy
- Type type=typeof(Example);
- MethodInfo[] listMethodInfo=type.GetMethods();
- foreach(MethodInfo methodInfo in listMethodInfo)
- Cosole.WriteLine("Method name is "+methodInfo.Name);
2.我們也能通過反射方法執行類裡面的方法2.我們也能通過反射方法執行類裡面的方法
[csharp]view plaincopy
- 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代表沒有參數
四、反射屬性
1.通過 System.Reflection.PropertyInfo 能尋找到類裡面的屬性
常用的方法有GetValue(object,object[]) 擷取屬性值和 SetValue(object,object,object[]) 設定屬性值
四、反射屬性
1.通過 System.Reflection.PropertyInfo 能尋找到類裡面的屬性
常用的方法有GetValue(object,object[]) 擷取屬性值和 SetValue(object,object,object[]) 設定屬性值
四、反射屬性
1.通過 System.Reflection.PropertyInfo 能尋找到類裡面的屬性
常用的方法有GetValue(object,object[]) 擷取屬性值和 SetValue(object,object,object[]) 設定屬性值
[csharp]view plaincopy
- Type type=typeof(Example);
- PropertyInfo[] listPropertyInfo=type.GetProperties();
- foreach(PropertyInfo propertyInfo in listPropertyInfo)
- Cosole.WriteLine("Property name is "+ propertyInfo.Name);
2.我們也可以通過以下方法設定或者擷取一個對象的屬性值2.我們也可以通過以下方法設定或者擷取一個對象的屬性值
[csharp]view plaincopy
- 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
五、反射欄位
通過 System.Reflection.FieldInfo 能尋找到類裡面的欄位
它包括有兩個常用方法SetValue(object ,object )和GetValue(object) 因為使用方法與反射屬性非常相似,在此不再多作介紹
(略)
六、反射特性
通過System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一個類裡面的特性,以下例子可以反射出一個類的所有特性
五、反射欄位
通過 System.Reflection.FieldInfo 能尋找到類裡面的欄位
它包括有兩個常用方法SetValue(object ,object )和GetValue(object) 因為使用方法與反射屬性非常相似,在此不再多作介紹
(略)
六、反射特性
通過System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一個類裡面的特性,以下例子可以反射出一個類的所有特性
[csharp]view plaincopy
- 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屬性的所有特性
[csharp]view plaincopy
- publicclass 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的區別
1、Assembly.LoadFile只載入相應的dll檔案,比如Assembly.LoadFile("abc.dll"),則載入abc.dll,假如abc.dll中引用了def.dll的話,def.dll並不會被載入。
Assembly.LoadFrom則不一樣,它會載入dll檔案及其引用的其他dll,比如上面的例子,def.dll也會被載入。
2、用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 不能用於載入標識相同但路徑不同的程式集。
總結:
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的區別
1、Assembly.LoadFile只載入相應的dll檔案,比如Assembly.LoadFile("abc.dll"),則載入abc.dll,假如abc.dll中引用了def.dll的話,def.dll並不會被載入。
Assembly.LoadFrom則不一樣,它會載入dll檔案及其引用的其他dll,比如上面的例子,def.dll也會被載入。
2、用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 不能用於載入標識相同但路徑不同的程式集。
轉自 Lyncai的專欄 特別感謝Lyncai
C#反射Assembly 詳細說明