在專案中,程式集間的相互引用是經常遇到的。比如,主程式引用各分模組,各分模組引用公用程式集,以及平行的程式集間為了某些功能的實現也需要相互引用。這樣的引用一方面是迫不得已的選擇,而另一方面也反映出系統設計的水平。下面,簡單介紹一下c#中的一種機制——反射。反射可以在避免某些情況下的程式集引用問題,比如主程式引用各功能模組的問題,當然其它模組間也是可以用反射的,只是使用是否方便這些問題需要在使用前根據實際情況進行考慮。本文以主程式載入分模組為例,介紹一下反射的使用。
所謂反射,就是對程式集或模組利用基礎型別進行解析,然後還原出乙個物件模型,在呼叫者工作域裡執行的乙個過程。其核心部分就是解析。工作原理是這樣的。
無論你建立的多麼結構複雜的類,歸根結底都是由元資料構成的。如下,
public class person
private string name;
private int age;
private string content;
在程式編譯時,編譯器會建立型別表,字段表,方法表或其它表。再利用system.reflection命名空間中的包含的型別進行解析,也可以看成對比的過程,將要被反射的程式集中的表讀出,根據system.reflection的基本型別,進行重組,從而還原出原來程式集的結構。
例如,序列化的過程就是使用了反射,序列化格式器將被序列化的物件中的字段的值獲取出來,然後寫入乙個位元組流,進行傳輸;因為位元組流傳輸不容易出錯或資訊丟失。接收到位元組流後,根據基本型別再還原出原物件的模型。
反射中,system.type型別很重要,它遍歷被反射的表中的型別和反射中的基本型別進行比較,然後判斷出當前是什麼型別。
簡單了解了原理,那麼再看如何使用的。
建乙個工程,包含主程式和子程式集,如圖
子程式的程式入口需要遵循一些約定,比如入口類名字需要都一樣,這樣才可統一載入。
namespace refleclibrary2
public class mainwindow
public mainwindow()
welcome();
private void welcome()
console.write(@"當前程式為:refleclibrary2 ");
console.writeline(@"開始執行refleclibrary2!");
namespace reflectlibrary1
public class mainwindow
public mainwindow()
welcome();
private void welcome()
console.write(@"當前程式為:reflectlibrary1 ");
console.writeline(@"開始執行refleclibrary1!");
然後看呼叫的部分,
class program
static void main(string args)
/設定約定的規則,比如需要載入的程式的目錄,程式集程式入口的類///
string suffix=@".dll";
string commonmainclass = @"mainwindow";
directoryinfo directory = new directoryinfo(startpath);
/將程式集檔名讀入,這裡其實只需要string型別的路徑即可,
//為了後面處理字串方便所以才讀取檔案資訊
var libraries = directory.getfiles().orderby(o=>o.fullname);
list loaddlls = new list();
if (libraries != null)
foreach (fileinfo item in libraries)
if (item.fullname.tolower().endswith(suffix))
loaddlls.add(item);
/執行程式集///
//程式集1
assembly assembly1 = assembly.loadfile(loaddlls[0].fullname.replace(@"/", @"\"));
string typename1 = loaddlls[0].name.replace(loaddlls[0].extension,string.empty) + @"." + commonmainclass;
assembly1.createinstance(typename1);
//程式集2
assembly assembly2 = assembly.loadfile(loaddlls[1].fullname.replace(@"/", @"\"));
string typename2 = loaddlls[1].name.replace(loaddlls[0].extension, string.empty) + @"." + commonmainclass;
assembly2.createinstance(typename2);
console.readline();
各個部分的作用都寫在了注釋中。
執行結果就是,程式集1和程式集2中的方法都執行了。當然這裡只是為了方便說明只寫了乙個方法,實際上
public mainwindow()
welcome();
C 中的反射原理及應用
反射的概述 反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 syste...
C 中的反射原理及應用
反射的概述 反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析 這些元資料表的 和反射相關...
C 中的反射原理及應用
注 本文 滄海桑田的部落格 反射的概述 反射的定義 審查元資料並收集關於它的型別資訊的能力。元資料 編譯以後的最基本資料單元 就是一大堆的表,當編譯程式集或者模組時,編譯器會建立乙個類定義表,乙個字段定義表,和乙個方法定義表等,system.reflection命名空間包含的幾個類,允許你反射 解析...