關於c#的程式集和反射,歷來都是兵家必爭之話題。
首先我們來看程式集,程式集是**進行編譯是的乙個邏輯單元,把相關的**和型別進行組合,然後生成pe檔案(例如可執行檔案.exe和類庫檔案.dll)。由於程式集在編譯後並不一定會生成單個檔案,而可能會生成多個物理檔案,甚至可能會生成分布在不同位置的多個物理檔案,所以程式集是乙個邏輯單元,而不是乙個物理單元。即程式集在邏輯上是乙個編譯單元,但在物理儲存上可以有多種存在形式。對於靜態程式集可以生成單個或多個檔案,而動態程式集是存在於記憶體中的。在c#中程式集處處可見,因為任何基於.net的**在編譯時都至少存在乙個程式集(所有.net專案都會預設引用mscorlib程式集)。
基於.net框架的.dll庫是乙個完整的程式集,需要事先引用對應的類庫。從**的結構上看,乙個程式集可以包含乙個或多個命名空間,而每個命名空間中又可以包含子命名空間或型別列表。由於程式集在編譯後可以生成多個模組檔案,因此乙個物理檔案並不代表它就是乙個程式集,乙個程式集並不一定只有乙個檔案。不過,在vs開發環境中,乙個解決方案可以包含多個專案,而每個專案就是乙個程式集。
程式集資訊其實是通過在程式集上應用各種attribute來設定的,並且這些特性都位於system.reflection命名空間,也就是這一系列attribute提供給反射技術,可用於獲取程式集的基本資訊.
應用程式結構分為應用程式域—程式集—模組—型別—成員幾個層次,公共語言執行庫載入器管理應用程式域,這種管理包括將每個程式集載入到相應的應用程式域以及控制每個程式集中型別層次結構的記憶體布局。
程式集包含模組,而模組包含型別,型別又包含成員,反射則提供了封裝程式集、模組和型別的物件。我們可以使用反射動態地建立型別的例項,將型別繫結到現有物件或從現有物件中獲取型別,然後呼叫型別的方法或訪問其字段和屬性。反射通常具有以下用途。
(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了解引數的名稱、資料型別、是輸入引數還是輸出引數,以及引數在方法簽名中的位置等。
動態引導程式集:
(1)通過程式集的長名稱載入,一般用於載入位於全域性程式集快取中的程式集。(.net框架的類庫都位於全域性程式集快取中)(使用gacutil命令列工具可以獲取system程式集的長名稱);
(2)通過指定的檔案引導程式集,通常是.dll或.exe檔案。
例如:本人的計算機上的全域性程式集快取包含下列程式集:
system, version=2.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089, processorarchitecture=msil
system, version=4.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089, processorarchitecture=msil
專案數 = 2
反射(reflection)是.net中的重要機制,通過反射,可以在執行時獲得.net中每乙個型別(包括類、結構、委託、介面和列舉等)的成員,包括方法、屬性、事件,以及建構函式等。還可以獲得每個成員的名稱、限定符和引數等。有了反射,即可對每乙個型別瞭如指掌。如果獲得了建構函式的資訊,即可直接建立物件,即使這個物件的型別在編譯時還不知道。
1)反射用於獲取型別資訊。下面乙個例子:、
using system;
using system.collections
.generic
;using system.linq
;using system.text
;using system.threading
.tasks
;using system.reflection
;namespace my
,屬性型別:", p.name, p.propertytype
.name);
}// 獲取button型別的公共事件列表
eventinfo events = typeofbutton.getevents();
// 輸出事件資訊
console.writeline("\n button類的公共事件列表:");
foreach (eventinfo ev in events)
,事件型別:", ev.name, ev.eventhandlertype
.name);}}
console.read();}}
}
2)反射還可以在執行階段動態建立型別例項,然後就可以動態呼叫例項的成員。
動態建立例項有兩種方法可以選擇:
第一種:使用activator類的createinstance靜態方法,其中方法返回的物件就是對應的例項引用。
看個例子:
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.reflection;
namespace me
: ", p.name, p.getvalue(instance));}}
}console.read();}}
public
class test
public
test(int sead)
}}
第二種:通過反射找出型別的建構函式,然後呼叫建構函式來獲取例項引用。
**如下:
using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.reflection;
namespace my
); if (constructor != null)
);// 獲取例項的屬性列表
if (instance != null)
:", p.name, objval ?? string.empty);}}
}}
console.read();}}
}
追求安逸與享樂,我把它稱之為豬欄的理想。 c 程式集及反射
程式層次 1.獲取當前應用程式域下的所有應用程式集 2.獲取乙個程式集下的類 assembly assm assembly.loadfile d 完成專案 2014 3 14 kongzhitai xml testlei bin debug testlei.dll type types assm.g...
程式集載入和反射
元資料表是用一系列字段表,方法表,型別定義表組成的。可以利用system.reflection命名空間中包含的型別,可以寫 來反射這些元資料表。具體的反射機制我是這樣理解的 首先應該清楚的了解到,system.reflection命名空間中的型別為程式集或模組中包含的換資料表提供了乙個物件模型 通過...
程式集載入和反射
最近一直都在看關於程式集載入和反射方面的資料,所以在這裡把我所學習到的東西記錄下來,方便自己以後複習,也給園子裡面不懂的朋友參考。net中反射在執行中過程中解析程式集中的元資料,獲得型別中的成員 包括字段 構造器 方法 屬性 事件等 資訊。把下面的類放在乙個類庫工程中,並編譯生成程式集 例如為cla...