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

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

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

 

复制代码
代码
1 using System;
2  using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Reflection.Emit;
6 using System.Reflection;
7 using Evlon.Util.Dynamic;
8
9 namespace ConsoleApplication2008
10 {
11 public class Program
12 {
13 static void Main(string[] args)
14 {
15 decimal ret = new Program().Dynamic("HelloWorld", Guid.NewGuid(), 2009);
16 Console.WriteLine(ret);
17
18 Console.ReadLine();
19 }
20
21 public decimal HelloWorld(Guid userId, int year)
22 {
23 return userId.GetHashCode() + year;
24 }
25 }
26
27 }
28 namespace Evlon.Util.Dynamic
29 {
30 public static class TypeExtension
31 {
32 public static decimal Dynamic(this object inst, string methodName, Guid userId, int year)
33 {
34 Type instType = inst.GetType();
35 Type[] paramTypes = new Type[] { typeof(object), typeof(Guid), typeof(int) };
36 Type[] paramMethodTypes = new Type[] { typeof(Guid), typeof(int) };
37 var dynamicMethod = new DynamicMethod("", typeof(decimal), paramTypes, true);
38 MethodInfo stringMethod = inst.GetType().GetMethod(methodName, paramMethodTypes);
39
40 var ilGen = dynamicMethod.GetILGenerator();//IL生成器
41
42 //声明变量
43 ilGen.DeclareLocal(instType);
44
45
46 //把参数推到堆栈上
47 ilGen.Emit(OpCodes.Ldarg_0);
48
49 //把参数1转化成指定的类型
50 ilGen.Emit(OpCodes.Castclass, instType);
51 ilGen.Emit(OpCodes.Stloc_0);
52
53 //加载参数
54 ilGen.Emit(OpCodes.Ldloc_0);
55 ilGen.Emit(OpCodes.Ldarg_1);
56 ilGen.Emit(OpCodes.Ldarg_2);
57
58 //调用方法
59 ilGen.Emit(OpCodes.Callvirt, stringMethod);
60 ilGen.Emit(OpCodes.Ret);//结束并返回值
61
62 //生成委托
63 Func<object, Guid, int, decimal> gan = (Func<object, Guid, int, decimal>)dynamicMethod.CreateDelegate(typeof(Func<object, Guid, int, decimal>));
64
65 //调用委托返回结果
66 return gan(inst, userId, year);
67 }
68
69 }
70 }
71
复制代码

 

posted @   阿牛  阅读(2920)  评论(3编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· Qt个人项目总结 —— MySQL数据库查询与断言
点击右上角即可分享
微信分享提示