C 提高知識 001 反射的應用和原理(一)

2021-06-20 02:03:32 字數 2637 閱讀 7696

在專案中,程式集間的相互引用是經常遇到的。比如,主程式引用各分模組,各分模組引用公用程式集,以及平行的程式集間為了某些功能的實現也需要相互引用。這樣的引用一方面是迫不得已的選擇,而另一方面也反映出系統設計的水平。下面,簡單介紹一下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命名空間包含的幾個類,允許你反射 解析...