目錄
反射的概述 反射
反射單個程式集
利用反射獲取型別資訊
設定反射型別的成員
通過反射建立型別的例項
反射型別的介面
反射的效能
反射的概述
反射的定義:審查元資料並收集關於它的型別資訊的能力。元資料(編譯以後的最基本資料單元)就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,。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 開發編譯器的開發使用的,所以你要意識到不是所有的反射型別都是適合每個人的。
反射
}
反射單個程式集
上面的方法講的是反射
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 與上乙個方法類似,不過需要指定型別及其程式集
3.
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 中的反射
反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 system.refl...
c 中的反射
反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 system.refl...