2012年3月20日 星期二

委派與反射

委派就是要委託某個執行方法,但是,若是這個執行方法必須要在 RunTime 才能決定的話,那要如何設計這個委派呢?

問題

假設存在底下二個類別,我們要委派執行 MethodB ,但是,必須在 RunTime 時才能決定對象到底是 Class1.MethodB 或 Class2.MethodB

public class Class1
{
    public int MethodB(int a)
    {
        return a + a;
    }
}

public class Class2
{
    public int MethodB(int a)
    {
        return a * a;
    }
}

一般做法

底下是常用的委派使用方法,在實體化委派時,就同時指明 invoke 的方法名稱,如下列程式碼:

public delegate int DelegateMethod(int x);

private void btnGeneralInvoke_Click(object sender, EventArgs e)
{
    Class1 c1 = new Class1();
    Class2 c2 = new Class2();

    //實體化委派
    DelegateMethod theDelegate = new DelegateMethod(c1.MethodB);

    //Invoke
    int a = theDelegate(3);
    MessageBox.Show(a.ToString());
}

使用 Reflection + DynamicInvoke

要達到上述問題的要求,可以使用 Reflection 方法搭配委派的動態呼叫來做。其簡單步驟就是:

CreateDelegate 有多個多載方法,底下是其中幾個:

public static Delegate CreateDelegate(Type type, MethodInfo method)
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method);
public static Delegate CreateDelegate(Type type, Type target, string method);
private void btnReflectionInvoke_Click(object sender, EventArgs e)
{
    //======================================================================================
    // 使用 Reflection 方法,動態載入組件,並取得指定的執行方法物件 MethodInfo
    //======================================================================================

    //動態載入組件
    string dll_file = @"D:\MCTS\MCTS2011\Practice\ClassLibrary3\bin\Debug\dll";
    Assembly asm = Assembly.LoadFile(dll_file);

    //由 UI 決定執行哪一個類別的方法
    string className = txtClass.Text;

    //由組件取得型別物件
    Type MyType = asm.GetType(className);

    //由型別物件取得方法物件
    MethodInfo MyMethod = MyType.GetMethod("MethodB", new Type[]{typeof(int)});

    //======================================================================================
    // 委派叫用
    //======================================================================================

    // 建立指定型別的委派
    Delegate theDelegate = Delegate.CreateDelegate(typeof(DelegateMethod), null, MyMethod);

    // DynamicInvoke 動態叫用委派的方法
    int a = (int) theDelegate.DynamicInvoke(3);
    MessageBox.Show(a.ToString());
}

沒有留言:

張貼留言