您的位置:首页 > 其它

使用Emit动态调用方法(技术原型)

2009-12-13 15:30 477 查看
上周五快下班时,看到一个博友BillGan文章:DynamicMethod (JIT Compiler encountered an internal limitation. )我还是相信中国人 ,当时没有太多时间,只是实现了调用静态方法的访问,不能称为动态方法调用。今天看到,BillGan好像已经死心了。

不过,其实没有那么绝望的吧,我实现了一个原型,原理是使用Emit声明一个变量,然后强制类型转化成类型,最后再去调用方法:

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using Evlon.Util.Dynamic;

namespace ConsoleApplication2008
{
public class Program
{
static void Main(string[] args)
{
decimal ret = new Program().Dynamic("HelloWorld", Guid.NewGuid(), 2009);
Console.WriteLine(ret);

Console.ReadLine();
}

public decimal HelloWorld(Guid userId, int year)
{
return userId.GetHashCode() + year;
}
}

}
namespace Evlon.Util.Dynamic
{
public static class TypeExtension
{
public static decimal Dynamic(this object inst, string methodName, Guid userId, int year)
{
Type instType = inst.GetType();
Type[] paramTypes = new Type[] { typeof(object), typeof(Guid), typeof(int) };
Type[] paramMethodTypes = new Type[] { typeof(Guid), typeof(int) };
var dynamicMethod = new DynamicMethod("", typeof(decimal), paramTypes, true);
MethodInfo stringMethod = inst.GetType().GetMethod(methodName, paramMethodTypes);

var ilGen = dynamicMethod.GetILGenerator();//IL生成器

//声明变量
ilGen.DeclareLocal(instType);

//把参数推到堆栈上
ilGen.Emit(OpCodes.Ldarg_0);

//把参数1转化成指定的类型
ilGen.Emit(OpCodes.Castclass, instType);
ilGen.Emit(OpCodes.Stloc_0);

//加载参数
ilGen.Emit(OpCodes.Ldloc_0);
ilGen.Emit(OpCodes.Ldarg_1);
ilGen.Emit(OpCodes.Ldarg_2);

//调用方法
ilGen.Emit(OpCodes.Callvirt, stringMethod);
ilGen.Emit(OpCodes.Ret);//结束并返回值

//生成委托
Func<object, Guid, int, decimal> gan = (Func<object, Guid, int, decimal>)dynamicMethod.CreateDelegate(typeof(Func<object, Guid, int, decimal>));

//调用委托返回结果
return gan(inst, userId, year);
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: