用反射通过构造函数给窗体传参
最近在項目上用到反射來調用方法用的比較多,傳參包含兩種方式,一種是通過變量傳參,第二種是通過構造函數傳參,下面分別介紹下兩種方式:
先介紹幾種獲取實例的方法,下面描述中提到的三種方法其實都是大同小異的,核心就是通過System.Reflection.Assembly 類型的CreateInstance方法創建實例。
//反射可以有很多方法,編寫程序時請先導入 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);那么簡單的解釋一下這種方法的原理:
1.找到要實例化的類所在的程序集,并將之實例為System.Reflection.Assembly 類的對象
2.利用System.Reflection.Assembly 類提供的CreateInstance方法,創建類的對象
?
一、通過變量傳參
通過變量傳參稍微簡單點,原理很簡單,先通過反射獲取到類,這里的類需要有個公共變量,然后將該類從object類型強制轉換為原本的類名,比如反射調用的DLL中原本類名是Class1,那么通過反射獲取創造該類后強制轉換為Class1,這樣就可以直接通過實例給類中的變量賦值。(注意:如果是調用外部的DLL,需要先引用該類的程序集)
先創建一個簡單類:
public class Class1{private string _strId;public string ID{get { return _strId; }set { _strId = value; }}public Class1(){}public Class1(string str){_strId = str;}}然后在主函數中加入代碼:
Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當前程序集 object obj = assembly.CreateInstance("ReflectionTest.Test"); //類的完全限定名(即包括命名空間) Class1 entity = obj as Class1; entity.ID = "xxxxx";調試結果:顯示obj對象的確不為空,證明這種方法可行。
?
二、通過構造函數傳參
通過構造函數傳參稍微復雜,首先修改Class1類,將其構造函數改為:
public Class1(string str) {_strId = str; }假設主函數還是用以前的那樣子調用,會直接拋出異常:未找到類型“ReflectionTest.Class1”上的構造函數。這是因為CreateInstance方法默認情況下是通過找無參數的構造函數去創建對象的,現在找不到當然會出錯,實時上CreateInstance方法提供了3中簽名,其中有CreateInstance(String, Boolean, BindingFlags, Binder,?Object?[], CultureInfo,?Object?[]) 就可以滿足這種情況:
修改主函數如下:
Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當前程序集 //object obj = assembly.CreateInstance("ReflectionTest.Class1"); //類的完全限定名(即包括命名空間) object[] parameters = new object[1]; parameters[0] = "test string"; object obj = assembly.CreateInstance("ReflectionTest.Class1",true,System.Reflection.BindingFlags.Default,null,parameters,null,null);// 創建類的實例測試后運行結果正常
?
繼續加深難度,創建string的對象
首先知道string是System.String的別名,所以要創建的是System.String的對象,而System.String在mscorlib.dll中,所以需要將mscorlib.dll實例為System.Reflection.Assembly的對象,這里利用System.Type類型的屬性Assembly來實現功能。
System.String的構造函數有很多種,本文中筆者就不墨跡了,采用String(?Char?[]) 。
最終將主函數中代碼改為:
Type type = Type.GetType("System.String"); object[] parameters = new object[1]; char[] lpChar = { 't','e','s','t' }; parameters[0] = lpChar;object obj = type.Assembly.CreateInstance("ReflectionTest.Class1",true,System.Reflection.BindingFlags.Default,null,parameters,null,null);// 創建類的實例調試結果:對象為空,失敗了,事實上這種方法還有個問題,如將Class1類構造函數修改為
public Test(string str) {ID = str;//屬性賦值 }調試結果:對象創建成功,但是變量為空
?
解決方案
采用System.Activator 類的CreateInstance方法。
最后見代碼:
Type type = Type.GetType("System.String"); object[] parameters = new object[1]; char[] lpCh = { 't', 'e', 's', 't' }; parameters[0] = lpCh;object obj = Activator.CreateInstance(type, parameters);調試結果:對象創建成功,且變量值正常
采用System.Activator 類的CreateInstance方法,要比System.Reflection.Assembly的CreateInstance簡單有效很多。有興趣的朋友可以仔細看看。
轉載于:https://www.cnblogs.com/xiangzhong/p/5391721.html
總結
以上是生活随笔為你收集整理的用反射通过构造函数给窗体传参的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 存储过程的作用
- 下一篇: 团队开发 个人工作总结01