C 中的反射

2021-04-01 16:35:04 字數 3199 閱讀 2560

反射的定義:審查元資料並收集關於它的型別資訊的能力。元資料(編譯以後的最基本資料單元)就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,。system.reflection命名空間包含的幾個類,允許你反射(解析)這些元資料表的**

system.reflection.memberinfo

system.reflection.eventinfo

system.reflection.fieldinfo

system.reflection.methodbase

system.reflection.constructorinfo

system.reflection.methodinfo

system.reflection.propertyinfo

system.type

system.reflection.assembly

反射的層次模型:

注:層次間都是一對多的關係

反射的作用:

1. 可以使用反射動態地建立型別的例項,將型別繫結到現有物件,或從現 有物件中獲取型別

2. 應用程式需要在執行時從某個特定的程式集中載入乙個特定的型別,以便實現某個任務時可以用到反射。

3. 反射主要應用與類庫,這些類庫需要知道乙個型別的定義,以便提供更多的功能。

應用要點:

1. 現實應用程式中很少有應用程式需要使用反射型別

2. 使用反射動態繫結需要犧牲效能

3. 有些元資料資訊是不能通過反射獲取的

4. 某些反射型別是專門為那些clr 開發編譯器的開發使用的,所以你要意識到不是所有的反射型別都是適合每個人的。

static void main }

反射單個程式集

1. load 方法:極力推薦的一種方法,load 方法帶有乙個程式集標誌並載入它,load 將引起clr把策略應用到程式集上,先後在全域性程式集緩衝區,應用程式基目錄和私有路徑下面查詢該程式集,如果找不到該程式集系統丟擲異常

2. loadfrom 方法:傳遞乙個程式集檔案的路徑名(包括副檔名),clr會載入您指定的這個程式集,傳遞的這個引數不能包含任何關於版本號的資訊,區域性,和公鑰資訊,如果在指定路徑找不到程式集丟擲異常。

3. loadwithpartialname:永遠不要使用這個方法,因為應用程式不能確定再在載入的程式集的版本。該方法的唯一用途是幫助那些在.net框架的測試環節使用.net 框架提供的某種行為的客戶,這個方法將最終被拋棄不用。

利用反射獲取型別資訊

前面講完了關於程式集的反射,下面在講一下反射層次模型中的第三個層次,型別反射

乙個簡單的利用反射獲取型別資訊的例子:

using system;

using sytem.reflection;

class reflecting

//定義乙個獲取反射內容的方法

void getreflectioninfo(assembly myassembly) }

} 其它幾種獲取type物件的方法:

1. system.type 引數為字串型別,該字串必須指定型別的完整名稱(包括其命名空間)

2. system.type 提供了兩個例項方法:getnestedtype,getnestedtypes

3. syetem.reflection.assembly 型別提供的例項方法是:gettype,gettypes,getexporedtypes

4. system.reflection.moudle 提供了這些例項方法:gettype,gettypes,findtypes

設定反射型別的成員

反射型別的成員就是反射層次模型中最下面的一層資料。我們可以通過type物件的getmembers 方法取得乙個型別的成員。如果我們使用的是不帶引數的getmembers,它只返回該型別的公共定義的靜態變數和例項成員,我們也可以通過使用帶引數的getmembers通過引數設定來返回指定的型別成員。具體引數參考msdn 中system.reflection.bindingflags 列舉型別的詳細說明。

例如:

//設定需要返回的型別的成員內容

bindingflags bf=bingdingflags.declaredonly|bingdingflags.nonpublic|bingdingflags.public;

foreach (memberinfo mi int t.getmembers(bf))

通過反射建立型別的例項

通過反射可以獲取程式集的型別,我們就可以根據獲得的程式集型別來建立該型別新的例項,這也是前面提到的在執行時建立物件實現晚繫結的功能

我們可以通過下面的幾個方法實現:

1. system.activator 的createinstance方法。該方法返回新物件的引用。具體使用方法參見msnd

2. system.activator 的createinstancefrom 與上乙個方法類似,不過需要指定型別及其程式集

4. system.type的invokemember例項方法:這個方法返回乙個與傳入引數相符的建構函式,並構造該型別。

5. system.reflection.constructinfo 的invoke例項方法

反射型別的介面

如果你想要獲得乙個型別繼承的所有介面集合,可以呼叫type的findinte***ces getinte***ce或者getinte***ces。所有這些方法只能返回該型別直接繼承的介面,他們不會返回從乙個介面繼承下來的介面。要想返回介面的基礎介面必須再次呼叫上述方法。

反射的效能:

使用反射來呼叫型別或者觸發方法,或者訪問乙個字段或者屬性時clr 需 要做更多的工作:校驗引數,檢查許可權等等,所以速度是非常慢的。所以盡量不要使用反射進行程式設計,對於打算編寫乙個動態構造型別(晚繫結)的應用程式,可以採取以下的幾種方式進行代替:

1. 通過類的繼承關係。讓該型別從乙個編譯時可知的基礎型別派生出來,在執行時生成該類 型的乙個例項,將對其的引用放到其基礎型別的乙個變數中,然後呼叫該基礎型別的虛方法。

2. 通過介面實現。在執行時,構建該型別的乙個例項,將對其的引用放到其介面型別的乙個變數中,然後呼叫該介面定義的虛方法。

3.通過委託實現。讓該型別實現乙個方法,其名稱和原型都與乙個在編譯時就已知的委託相符。在執行時先構造該型別的例項,然後在用該方法的物件及名稱構造出該委託的例項,接著通過委託呼叫你想要的方法。這個方法相對與前面兩個方法所作的工作要多一些,效率更低一些

c 中的反射

反射 reflection 是.net中的重要機制,通過放射,可以在執行時獲得.net中每乙個型別 包括類 結構 委託 介面和列舉等 的成員,包括方法 屬性 事件,以及建構函式等。還可以獲得每個成員的名稱 限定符和引數等。有了反射,即可對每乙個型別瞭如指掌。如果獲得了建構函式的資訊,即可直接建立物件...

c 中的反射

目錄 反射的概述 反射 反射單個程式集 利用反射獲取型別資訊 設定反射型別的成員 通過反射建立型別的例項 反射型別的介面 反射的效能 反射的概述 反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙...

c 中的反射

反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 system.refl...