C#利用反射動態(tài)創(chuàng)建對象 帶參數(shù)的構(gòu)造函數(shù)和String類型
當(dāng)前位置:點(diǎn)晴教程→知識管理交流
→『 技術(shù)文檔交流 』
最近筆者有一個(gè)想法需要利用反射動態(tài)創(chuàng)建對象(如string,int,float,bool,以及自定義類等)來實(shí)現(xiàn),一直感覺反射用不好,特別是當(dāng)構(gòu)造函數(shù)帶參數(shù)的時(shí)候。
MSDN上給出的例子十分復(fù)雜,網(wǎng)上的帖子則一般都說很簡單,那就看看網(wǎng)上比較普遍的說法: 01. “反射”其實(shí)就是利用程序集的元數(shù)據(jù)信息。 02. 03. 反射可以有很多方法,編寫程序時(shí)請先導(dǎo)入 System.Reflection 命名空間,假設(shè)你要反射一個(gè) DLL 中的類,并且沒有引用它(即未知的類型): 04. Assembly assembly = Assembly.LoadFile( "程序集路徑,不能是相對路徑" ); // 加載程序集(EXE 或 DLL) 05. object obj = assembly.CreateInstance( "類的完全限定名(即包括命名空間)" ); // 創(chuàng)建類的實(shí)例 06. 07. 若要反射當(dāng)前項(xiàng)目中的類可以為: 08. 09. Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當(dāng)前程序集 10. object obj = assembly.CreateInstance( "類的完全限定名(即包括命名空間)" ); // 創(chuàng)建類的實(shí)例,返回為 object 類型,需要強(qiáng)制類型轉(zhuǎn)換 11. 12. 也可以為: 13. Type type = Type.GetType( "類的完全限定名" ); 14. object obj = type.Assembly.CreateInstance(type); 15. 16. 反射創(chuàng)建類的實(shí)例 因?yàn)檫@段描述在很多地方都有看到,筆者也不知道原始出處,所以這里就給出筆者第一次看到的地方:http://hi.baidu.com/rayord/item/92e58ddb0d34c13de3108fbb 上述描述中提到的三種方法其實(shí)都是大同小異的,核心就是通過System.Reflection.Assembly 類型的CreateInstance方法創(chuàng)建實(shí)例。 關(guān)于System.Reflection.Assembly 類可以直接在MSDN上查詢詳細(xì)信息http://msdn.microsoft.com/zh-cn/library/system.reflection.assembly(v=vs.110).aspx 那么簡單的解釋一下這種方法的原理: 1.找到要實(shí)例化的類所在的程序集,并將之實(shí)例為System.Reflection.Assembly 類的對象 2.利用System.Reflection.Assembly 類提供的CreateInstance方法,創(chuàng)建類的對象 看起來確實(shí)很簡單,只是這種方法真的好用么? 筆者進(jìn)行了測試以說明: 第一次測試,創(chuàng)建一個(gè)簡單的自定義類型對象 首先創(chuàng)建一個(gè)類: 01. class Test 02. { 03. private string _strId; 04. public string ID 05. { 06. get { return _strId; } 07. set { _strId = value; } 08. } 09. 10. public Test() 11. { 12. } 13. } 然后在主函數(shù)中加入代碼: Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當(dāng)前程序集 object obj = assembly.CreateInstance("ReflectionTest.Test"); //類的完全限定名(即包括命名空間) 調(diào)試結(jié)果:顯示obj對象的確不為空,證明這種方法可行。 第二次測試,加深難度,測試類的構(gòu)造函數(shù)需要傳遞參數(shù) public Test(string str) { _strId = str; } 調(diào)試結(jié)果:直接拋出異常:未找到類型“ReflectionTest.Test”上的構(gòu)造函數(shù)。這是因?yàn)镃reateInstance方法默認(rèn)情況下是通過找無參數(shù)的構(gòu)造函數(shù)去創(chuàng)建對象的,現(xiàn)在找不到當(dāng)然會出錯(cuò),實(shí)時(shí)上CreateInstance方法提供了3中簽名,其中有CreateInstance(String, Boolean, BindingFlags, Binder, Object [], CultureInfo, Object []) 就可以滿足這種情況: 修改主函數(shù)如下: 1. Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當(dāng)前程序集 2. //object obj = assembly.CreateInstance("ReflectionTest.Test"); //類的完全限定名(即包括命名空間) 3. object [] parameters = new object [1]; 4. parameters[0] = "test string" ; 5. object obj = assembly.CreateInstance( "ReflectionTest.Test" , true ,System.Reflection.BindingFlags.Default, null ,parameters, null , null ); // 創(chuàng)建類的實(shí)例 調(diào)試結(jié)果:正常,并且對象中變量值也是正確的,但是這離筆者的需求還差很遠(yuǎn)。繼續(xù) 首先知道string是System.String的別名,所以要創(chuàng)建的是System.String的對象,而System.String在mscorlib.dll中,所以需要將mscorlib.dll實(shí)例為System.Reflection.Assembly的對象,這里利用System.Type類型的屬性Assembly來實(shí)現(xiàn)功能。 System.String的構(gòu)造函數(shù)有很多種,本文中筆者就不墨跡了,采用String( Char []) 。 最終將主函數(shù)中代碼改為: 1. Type type = Type.GetType( "System.String" ); 2. object [] parameters = new object [1]; 3. char [] lpChar = { ''t'' , ''e'' , ''s'' , ''t'' }; 4. parameters[0] = lpChar; 5. 6. object obj = type.Assembly.CreateInstance( "ReflectionTest.Test" , true ,System.Reflection.BindingFlags.Default, null ,parameters, null , null ); // 創(chuàng)建類的實(shí)例 調(diào)試結(jié)果:對象為空,失敗了,事實(shí)上這種方法還有個(gè)問題,如將Test類構(gòu)造函數(shù)修改為 1. public Test( string str) 2. { 3. ID = str; //屬性賦值 4. } 調(diào)試結(jié)果:對象創(chuàng)建成功,但是變量為空 以上問題詳細(xì)原因筆者現(xiàn)在也無法解釋,正在查找相關(guān)資料。 解決方案 采用System.Activator 類的CreateInstance方法。 最后見代碼: 1. Type type = Type.GetType( "System.String" ); 2. object [] parameters = new object [1]; 3. char [] lpCh = { ''t'' , ''e'' , ''s'' , ''t'' }; 4. parameters[0] = lpCh; 5. 6. object obj = Activator.CreateInstance(type, parameters); 調(diào)試結(jié)果:對象創(chuàng)建成功,且變量值正常 結(jié)論 采用System.Activator 類的CreateInstance方法,要比System.Reflection.Assembly的CreateInstance簡單有效很多。有興趣的朋友可以仔細(xì)看看。 該文章在 2017/4/5 0:36:30 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |