有需求或技術問題可以隨時跟我連絡 (MSN上線時)

2009年8月26日 星期三

Reflection in C#

System.Reflection 這個Name Space,有著強大的Hack Function.

以下是MSDN對它的一些描述

反映(Reflection)概觀

Common Language Runtime 載入器可管理 應用程式定義域,這些定義域可在具有相同應用程式範圍的物件周圍構成定義的界限。這個管理包括載入各個組件至適當應用程式定義域,和控制各個組件內型別階層架構的記憶體配置。

組件包含模組,模組包含型別,而型別包含成員。反映提供封裝組件、模組和型別的物件。您可以使用反映,動態建立型別的執行個體、繫結型別至現有物件,或從現有物件取得型別。您可以接著叫用型別的方法,或存取它的欄位和屬性。反映的一般用法如下所示:

  • 使用 Assembly 定義並載入組件、載入組件資訊清單 (Assembly Manifest) 中列出的模組,和從這個組件找出型別並建立它的執行個體。

  • 使用 Module 探索資訊,例如包含模組和模組中類別的組件。您也可以取得所有全域方法或是在模組上定義的其他特定非全域方法。

  • 使用 ConstructorInfo 探索資訊,例如名稱、參數、存取修飾詞 (例如 publicprivate),以及建構函式的實作 (Implementation) 詳細資訊 (例如 abstractvirtual)。使用 TypeGetConstructorsGetConstructor 方法,叫用特定的建構函式。

  • 使用 MethodInfo 探索資訊,例如名稱、傳回型別、參數、存取修飾詞 (例如 publicPrivate),以及方法的實作詳細資訊 (例如 abstractvirtual)。使用 TypeGetMethodsGetMethod 方法,叫用特定方法。

  • 使用 FieldInfo 探索資訊,例如名稱、存取修飾詞 (例如 publicprivate),以及欄位的實作詳細資訊 (例如 static),並取得或設定欄位值。

  • 使用 EventInfo 探索資訊,例如名稱、事件處理常式資料型別、自訂屬性、宣告型別和事件的反映型別,並加入或移除事件處理常式。

  • 使用 PropertyInfo 探索資訊,例如名稱、資料型別、宣告型別、反映型別和屬性的唯讀或可寫入狀態,並取得或設定屬性值。

  • 使用 ParameterInfo 探索資訊,例如參數的名稱、資料型別、參數是否為輸入或輸出參數,和方法簽章 (Signature) 中參數的位置。

  • 使用 CustomAttributeData 探索在應用程式定義域的僅限反映內容中工作時,關於自訂屬性的資訊。CustomAttributeData 讓您可以檢查屬性,而不需要建立這些屬性的執行個體。

System.Reflection.Emit 命名空間的類別提供反映的特殊形式,允許您在 Run Time 建置型別。

反映也可以用來建立稱為型別瀏覽器的應用程式,允許使用者選取型別並接著檢視那些型別的資訊。

反映還有其他用法。語言編譯器,例如 JScript,會使用反映建構符號表。 System.Runtime.Serialization 命名空間中的類別會使用反映存取資料,並判斷哪個欄位要保存 (Persist)。 System.Runtime.Remoting 命名空間中的類別會透過序列化 (Serialization) 間接使用反映。

 

不說廢話,來一個範例看看它的威力,先看一下程式大概架構,如下圖所示

2009-8-26 下午 04-12-53 方案中有兩個專案,(1)TEST(2)物件Reflection

(1)TEST : 在 FormTest.cs 新增 (其他啥事都不做)

private int Add(int a, int b)
{
    return a + b;
}

(2)物件Reflection : FormReflection Layout如上圖,FormReflection.cs新增兩個Button Event

private void button2_Click(object sender, EventArgs e)
{
    OpenFileDialog myOFD = new OpenFileDialog();
    myOFD.Filter = "*.exe|*.EXE";
    if (myOFD.ShowDialog() == DialogResult.OK)
        textBox4.Text = myOFD.FileName;
}
private void button1_Click(object sender, EventArgs e)
{
    Assembly myAssembly = Assembly.LoadFile(textBox4.Text);
    Type myType = myAssembly.GetType("EST.FormTEST");
    object MyInstance = Activator.CreateInstance(myType);
    textBox3.Text = myType.InvokeMember("Add",
                    BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
                    null, MyInstance, new object[] { int.Parse(textBox1.Text), int.Parse(textBox2.Text) }).ToString();
}

原理:

按下FormReflection button2,選取Test.exe所在路徑

按下FormReflection button1,Call Test.exe 的TEST.FormTEST Add(…),完成運算

2009-8-26 下午 04-48-18

以上只是一個最簡單的範例,Reflection還有很多很強大的功能,有待研究...

Source Code [MD5 : 4fbf53d221d4605190bc048f57e32b39]



沒有留言:

張貼留言