.NET 动态调用那些事
传统方法和委托调用
/// <summary>
/// the English speaker.
/// </summary>
/// <param name="name">The name.</param>
public void EnglishSpeaker(string name)
{
Console.WriteLine(
string.Format("Hello my name is {0} and I am English speaker.\n", name));
}
/// <summary>
/// the Chineses speaker.
/// </summary>
public void ChineseSpeaker(string name)
{
Console.WriteLine(
string.Format("您好我的名字叫{0},我是讲普通话的。\n", name));
}
(1)不使用委托调用的方式:
/// <summary>
/// 根据上下文调用不同的方法
/// </summary>
/// <param name="name">string</param>
/// <param name="lang">enum</param>
private static void Say(string name, Language lang)
{
switch (lang)
{
case Language.Chinese:
Program.ChineseSpeaker(name);
break;
case Language.English:
Program.EnglishSpeaker(name);
break;
default :
break;
}
}
(2)使用委托调用:
/// <summary>
/// Define speak delegate.
/// </summary>
/// <param name="name"></param>
private delegate void SpeakDelegate(string name);
/// <summary>
/// The base say function.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="speaker">The speaker.</param>
private static void Say(string name, SpeakDelegate speaker)
{
///Inoke the speaker function.
speaker(name);
}
///传递函数名进行委托方法绑定
Program.Say("钧航", ChineseSpeaker);
Program.Say("JK.Rush", EnglishSpeaker);
动态调用方法:
(1)反射发出调用
使用 DynamicMethod 类在运行时定义轻量全局方法,然后使用委托执行这些方法。
public class MyMath { public double Add1(int a, float b) { return a + b; } public double Add2(int a,float b) { return a+b+3; } }
var addMethod = typeof(MyMath).GetMethod("Add1"); var dynamicMethod = new DynamicMethod("", typeof(double), new[] { typeof(MyMath), typeof(int), typeof(float) }); // var il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, addMethod); il.Emit(OpCodes.Ret); // var add = (Func<MyMath, int, float, double>)dynamicMethod.CreateDelegate(typeof(Func<MyMath, int, float, double>)); // var math = new MyMath(); var result = add(math, 1, 2.0);
从第 5 行起,使用几个 IL 汇编指令,简单一说:
- 第 5 行,OpCodes.Ldarg_0 是将索引为 0 的参数值推送到堆栈上,Ldarg_1、Ldarg_2 以此类推;
- 第 6 行,OpCodes.Callvirt 是调用对象的(后期绑定)方法,并且将返回值推送到计算堆栈上;
- 第 9 行,OpCodes.Ret 表达从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
反射发出是在汇编级别的,很底层,也就意味着效率更高、威力更强大。反射发出能绕过跳过 JIT 可见性检查,访问 private 成员。
(2)反射动态调用方法(略)http://www.cnblogs.com/focusonnet/archive/2009/04/17/1438013.html
未完待续

浙公网安备 33010602011771号