C 反射的使用

2021-10-19 12:56:50 字數 4370 閱讀 3680

使用反射的主要目的在於動態建立物件,由於物件存在於不同的程式集中,因此在動態建立物件時不但需要知道物件名稱,還需要物件所在的程式集路徑,應用而生出現了反射幫助我們解決了此問題。

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 ...