使用反射的主要目的在於動態建立物件,由於物件存在於不同的程式集中,因此在動態建立物件時不但需要知道物件名稱,還需要物件所在的程式集路徑,應用而生出現了反射幫助我們解決了此問題。
1.在程式執行時,動態獲取 程式集, 型別(class,inte***ce)和型別的成員資訊(方法,字段,屬性等)。
2.在程式執行時,動態建立 型別例項, 以及呼叫和方法 動態建立出來的 型別例項的成員。
3.反射的應用:框架(spring .net/ .net mvc等)
4.在程式執行時,動態獲取 程式集
/*「反射」其實就是利用程式集的元資料資訊。 反射可以有很多方法,編寫程式時請先導入
* system.reflection 命名空間,假設你要反射乙個 dll 中的類,並且沒有引用它(即未知的型別):
* assembly assembly = assembly.loadfile("程式集路徑,不能是相對路徑");
*/// 引導程式集(exe 或 dll)
object obj = assembly.createinstance("類的完全限定名(即包括命名空間)");
// 建立類的例項 若要反射當前專案中的類可以為:
assembly assembly = assembly.getexecutingassembly();
// 獲取當前程式集
object obj = assembly.createinstance("類的完全限定名(即包括命名空間)");
// 建立類的例項,返回為 object 型別,需要強制型別轉換 也可以為:
type type = type.gettype("類的完全限定名");
object obj = type.assembly.createinstance(type); //反射建立類的例項
因為這段描述在很多地方都有看到,筆者也不知道原始出處,所以這裡就給出筆者第一次看到的地方:
上述描述中提到的三種方法其實都是大同小異的,核心就是通過system.reflection.
關於system.reflection.
那麼簡單的解釋一下這種方法的原理:
1.找到要例項化的類所在的程式集,並將之例項為system.reflection.
2.利用system.reflection.
看起來確實很簡單,只是這種方法真的好用麼?
筆者進行了測試以說明:
第一次測試,建立乙個簡單的自定義型別物件
首先建立乙個類:
class test
set
}public test()
}
然後在主函式中加入**:
assembly assembly = assembly.getexecutingassembly(); // 獲取當前程式集 object obj = assembly.createinstance("reflectiontest.test"); //類的完全限定名(即包括命名空間)
除錯結果:顯示obj物件的確不為空,證明這種方法可行。
第二次測試,加深難度,測試類的建構函式需要傳遞引數
首先修改test類,將其建構函式改為:
public test(string str)除錯結果:直接丟擲異常:未找到型別「reflectiontest.test」上的建構函式。這是因為createinstance方法預設情況下是通過找無引數的建構函式去建立物件的,現在找不到當然會出錯,實時上createinstance方法提供了3中簽名,其中有createinstance(string, boolean, bindingflags, binder, object , cultureinfo, object ) 就可以滿足這種情況:
修改主函式如下:
assembly assembly = assembly.getexecutingassembly(); // 獲取當前程式集
//object obj = assembly.createinstance("reflectiontest.test"); //類的完全限定名(即包括命名空間)
object parameters = new object[1];
parameters[0] = "test string";
object obj = assembly.createinstance("reflectiontest.test",true,system.reflection.bindingflags.default,null,parameters,null,null);// 建立類的例項
除錯結果:正常,並且物件中變數值也是正確的,但是這離筆者的需求還差很遠。繼續
第三次測試,繼續加深難度,建立string的物件
首先知道string是system.string的別名,所以要建立的是system.string的物件,而system.string在mscorlib.dll中,所以需要將mscorlib.dll例項為system.reflection.
system.string的建構函式有很多種,本文中筆者就不墨跡了,採用string(
最終將主函式中**改為:
type type = type.gettype("system.string");
object parameters = new object[1];
char lpchar = ;
parameters[0] = lpchar; object obj = type.assembly.createinstance("reflectiontest.test",true,system.reflection.bindingflags.default,null,parameters,null,null);// 建立類的例項
除錯結果:物件為空,失敗了,事實上這種方法還有個問題,如將test類建構函式修改為
public test(string str)除錯結果:物件建立成功,但是變數為空
以上問題詳細原因筆者現在也無法解釋,正在查詢相關資料。
解決方案
採用system.activator 類的createinstance方法。
最後見**:
type type = type.gettype("system.string");
object parameters = new object[1];
char lpch = ;
parameters[0] = lpch;
object obj = activator.createinstance(type, parameters);
除錯結果:物件建立成功,且變數值正常
結論
採用system.activator 類的createinstance方法,要比system.reflection.assembly的createinstance簡單有效很多。有興趣的朋友可以仔細看看。
補充知識點
使用type.gettype(string typename)方法獲取型別時,引數typename中宣告的程式集沒有必要在當前專案中引用,只要放在生成專案的bin目錄下即可:
比如下面我構造了乙個類庫專案myclass包含類myclassobject
type mytype = type.gettype("myclass.myclassobject,myclass");是可以成功獲取到myclassobject的type型別的:
這說明c#中使用反射,在專案中不引用程式集也可以構造程式集中的類,只要將程式集檔案(dll檔案)放在和專案所生成檔案相同的資料夾(一般是bin目錄)下即可。
c 反射的使用
獲取具有指定名稱的type,執行區分大小寫的搜尋。tips gettype包括object.gettype 和type.gettype6個過載靜態方法 type ty type.gettype exthomeexpansion.view.zyl 通過引導程式集也可以獲得對應類的型別 其中load方法...
C 反射的使用
using system.reflection region 反射方法 根據路徑名稱反射指定方法 程式集名稱 類名稱 從程式集開始索引,如 bll.demo.demo 方法名 方法引數 public static string reflectionmethodfromname string asse...
C 反射使用示例
分享一下自己寫的使用反射的例子,包括根據名字獲取屬性值 字段 類的示例對,如自己申明的類或者list等 呼叫函式 無參 有參 介面如下 貼上 namespace relectiontest public int age 16 public men li new men 李四 private int ...