使用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
QQ:273352165
evlon#126.com
转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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数据库查询与断言