委派就是要委託某個執行方法,但是,若是這個執行方法必須要在 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 方法搭配委派的動態呼叫來做。其簡單步驟就是:
- 使用 Reflection 方法取得組件的方法資訊。
- 使用靜態的 Delegate.CreateDelegate 方法,建立委派執行個體。
- 叫用該委派個體的 DynamicInvoke 方法,動態 Invoke 指定的方法。
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());
}
沒有留言:
張貼留言