反射(reflection)是.net中的重要機制,通過放射,可以在執行時獲得.net中每乙個型別(包括類、結構、委託、介面和列舉等)的成員,包括方法、屬性、事件,以及建構函式等。還可以獲得每個成員的名稱、限定符和引數等。有了反射,即可對每乙個型別瞭如指掌。如果獲得了建構函式的資訊,即可直接建立物件,即使這個物件的型別在編譯時還不知道。
程式**在編譯後生成可執行的應用,我們首先要了解這種可執行應用程式的結構。
應用程式結構分為應用程式域—程式集—模組—型別—成員幾個層次,公共語言執行庫載入器管理應用程式域,這種管理包括將每個程式集載入到相應的應用程式域以及控制每個程式集中型別層次結構的記憶體布局。
程式集包含模組,而模組包含型別,型別又包含成員,反射則提供了封裝程式集、模組和型別的物件。我們可以使用反射動態地建立型別的例項,將型別繫結到現有物件或從現有物件中獲取型別,然後呼叫型別的方法或訪問其字段和屬性。反射通常具有以下用途。
(1)使用assembly定義和引導程式集,載入在程式集清單中列出模組,以及從此程式集中查詢型別並建立該型別的例項。
(2)使用module了解包含模組的程式集以及模組中的類等,還可以獲取在模組上定義的所有全域性方法或其他特定的非全域性方法。
(3)使用constructorinfo了解建構函式的名稱、引數、訪問修飾符(如pulic 或private)和實現詳細資訊(如abstract或virtual)等。使用type的getconstructors或getconstructor方法來呼叫特定的建構函式。
(4)使用methodinfo了解方法的名稱、返回型別、引數、訪問修飾符(如pulic 或private)和實現詳細資訊(如abstract或virtual)等。使用type的getmethods或getmethod方法來呼叫特定的方法。
(5)使用fiedinfo了解欄位的名稱、訪問修飾符(如public或private)和實現詳細資訊(如static)等,並獲取或設定字段值。
(6)使用eventinfo了解事件的名稱、事件處理程式資料型別、自定義屬性、宣告型別和反射型別等,新增或移除事件處理程式。
(7)使用propertyinfo了解屬性的名稱、資料型別、宣告型別、反射型別和唯讀或可寫狀態等,獲取或設定屬性值。
(8)使用parameterinfo了解引數的名稱、資料型別、是輸入引數還是輸出引數,以及引數在方法簽名中的位置等。
system.reflection.emit命名空間的類提供了一種特殊形式的反射,可以在執行時構造型別。
反射也可用於建立稱為型別瀏覽器的應用程式,使使用者能夠選擇型別,然後檢視有關選定型別的資訊。
此外,jscript等語言編譯器使用反射來構造符號表。system.runtime.serialization命名空間中的類使用反射來訪問資料並確定要永久儲存的字段,system.runtime.remoting命名空間中的類通過序列化來間接地使用反射。
5、如何根據型別來動態建立物件
system.activator提供了方法來根據型別動態建立物件,比如建立乙個datatable:
type t = type.gettype("system.data.datatable,system.data,version=1.0.3300.0, culture=neutral, publickeytoken=b77a5c561934e089");
datatable table = (datatable)activator.createinstance(t);
例二:根據有引數的構造器建立物件
namespace testspace
} }
… type t = type.gettype(「testspace.testclass」);
object constructparms = new object ; //構造器引數
testclass obj = (testclass)activator.createinstance(t,constructparms);
… 把引數按照順序放入乙個object陣列中即可
6、如何獲取方法以及動態呼叫方法
namespace testspace
public testclass(string value)
public string getvalue( string prefix )
public string value
get
} }
} 上面是乙個簡單的類,包含乙個有引數的構造器,乙個getvalue的方法,乙個value屬性,我們可以通過方法的名稱來得到方法並且呼叫之,如:
//獲取型別資訊
type t = type.gettype("testspace.testclass");
//構造器的引數
object constuctparms = new object;
//根據型別建立物件
object dobj = activator.createinstance(t,constuctparms);
//獲取方法的資訊
methodinfo method = t.getmethod("getvalue");
//呼叫方法的一些標誌位,這裡的含義是public並且是例項方法,這也是預設的值
bindingflags flag = bindingflags.public | bindingflags.instance;
//getvalue方法的引數
object parameters = new object;
//呼叫方法,用乙個object接收返回值
object returnvalue = method.invoke(dobj,flag,type.defaultbinder,parameters,null);
屬性與方法的呼叫大同小異,大家也可以參考msdn
7、動態建立委託
委託是c#中實現事件的基礎,有時候不可避免的要動態的建立委託,實際上委託也是一種型別:system.delegate,所有的委託都是從這個類派生的
system.delegate提供了一些靜態方法來動態建立乙個委託,比如乙個委託:
namespace testspace
public void getvalue(string value)
} }
使用示例:
testclass obj = new testclass();
//獲取型別,實際上這裡也可以直接用typeof來獲取型別
type t = type.gettype(「testspace.testclass」);
//建立**,傳入型別、建立**的物件以及方法名稱
testdelegate method = (testdelegate)delegate.createdelegate(t,obj,」getvalue」);
string returnvalue = method(「hello」);
C 中的反射
反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 system.refl...
c 中的反射
目錄 反射的概述 反射 反射單個程式集 利用反射獲取型別資訊 設定反射型別的成員 通過反射建立型別的例項 反射型別的介面 反射的效能 反射的概述 反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙...
c 中的反射
反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 system.refl...