前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >『.Net反射』ILGenerator.Emit 动态MSIL 编程

『.Net反射』ILGenerator.Emit 动态MSIL 编程

作者头像
yaphetsfang
发布于 2020-07-30 06:32:41
发布于 2020-07-30 06:32:41
42100
代码可运行
举报
文章被收录于专栏:yaphetsfangyaphetsfang
运行总次数:0
代码可运行

什么都不说,直接贴代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             SetValue();
 6         }
 7 
 8         public static void SetValue()
 9         {
10             int temp1 = 123;
11             int temp2 = 234;
12             int sum = temp1 + temp2;
13             string sumStr = sum.ToString();
14 
15             Console.WriteLine(sumStr);
16         }
17     }

对应的 ILGenerator.Emit 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1  class Program
  2     {
  3         static void Main(string[] args)
  4         {
  5 //.method public hidebysig static void  SetValue() cil managed
  6 //{
  7 //  // 代码大小       30 (0x1e)
  8 //  .maxstack  2
  9 //  .locals init ([0] int32 temp1,
 10 //           [1] int32 temp2,
 11 //           [2] int32 sum,
 12 //           [3] string sumStr)
 13 //  IL_0000:  nop
 14 //  IL_0001:  ldc.i4.s   123
 15 //  IL_0003:  stloc.0
 16 //  IL_0004:  ldc.i4     0xea
 17 //  IL_0009:  stloc.1
 18 //  IL_000a:  ldloc.0
 19 //  IL_000b:  ldloc.1
 20 //  IL_000c:  add
 21 //  IL_000d:  stloc.2
 22 //  IL_000e:  ldloca.s   sum
 23 //  IL_0010:  call       instance string [mscorlib]System.Int32::ToString()
 24 //  IL_0015:  stloc.3
 25 //  IL_0016:  ldloc.3
 26 //  IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
 27 //  IL_001c:  nop
 28 //  IL_001d:  ret
 29 //} // end of method Program::SetValue
 30             SetValue();
 31         }
 32 
 33         public static void SetValue()
 34         {
 35             DynamicMethod dm = new DynamicMethod("SetValueMethod", null, new Type[] { /*typeof(object), typeof(object)*/ }, true);
 36 
 37             ILGenerator generator = dm.GetILGenerator();
 38 
 39             generator.DeclareLocal(typeof(int));    //声明变量
 40             generator.DeclareLocal(typeof(int));    //声明变量
 41             generator.DeclareLocal(typeof(int));    //声明变量
 42             generator.DeclareLocal(typeof(string));    //声明变量
 43 
 44             //加载参数1,需要注意的是静态方法Ldarg_0对应的是参数1,
 45             //实例方法Ldarg_0对应的是this指针,Ldarg_1对应的是参数1,
 46             //即每个实例方法都传递一个隐含的this指针
 47 
 48             //int temp1 = 123;
 49             //int temp2 = 234;
 50             //int sum = temp1 + temp2;
 51             //string sumStr = sum.ToString();
 52             //Console.WriteLine(sumStr);
 53 
 54             //temp1 = 123
 55             generator.Emit(OpCodes.Ldc_I4, 123);
 56             generator.Emit(OpCodes.Stloc_0);
 57 
 58             //temp2 = 234
 59             generator.Emit(OpCodes.Ldc_I4, 234);
 60             generator.Emit(OpCodes.Stloc_1);
 61 
 62             //sum = temp1 + temp2
 63             generator.Emit(OpCodes.Ldloc_0);
 64             generator.Emit(OpCodes.Ldloc_1);
 65             generator.Emit(OpCodes.Add);
 66             generator.Emit(OpCodes.Stloc_2);
 67 
 68             //string sumStr = sum.ToString();
 69             //ldloca.s   sum
 70             //call       instance string [mscorlib]System.Int32::ToString()
 71             //stloc.3
 72             //调用成员函数
 73             generator.Emit(OpCodes.Ldloca_S, 2); //generator.Emit(OpCodes.Ldloc_2);
 74             MethodInfo toStringMethodInfo = typeof(Int32).GetMethod("ToString", new Type[] { });
 75             generator.Emit(OpCodes.Call, toStringMethodInfo);
 76             //generator.EmitCall(OpCodes.Call, toStringMethodInfo, null);   //和上面代码 同意思
 77             generator.Emit(OpCodes.Stloc_3);
 78 
 79             //Console.WriteLine(sumStr);
 80             //IL_0016:  ldloc.3
 81             //IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
 82             //调用静态函数
 83             generator.Emit(OpCodes.Ldloc_3);
 84             MethodInfo writeLineMethodInfo = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
 85             generator.Emit(OpCodes.Call, writeLineMethodInfo);
 86             //generator.EmitCall(OpCodes.Call, writeLineMethodInfo, null);   //和上面代码 同意思
 87 
 88             //generator.Emit(OpCodes.Pop);   //是否是 无返回值函数 调用之后,不用弹出堆栈?
 89 
 90             //return
 91             generator.Emit(OpCodes.Ret);   //函数执行完成
 92 
 93             
 94 
 95 
 96             //将函数作为 委托
 97             VoidNoParamsMethod delegateMethod = (VoidNoParamsMethod)dm.CreateDelegate(typeof(VoidNoParamsMethod));
 98             //执行委托
 99             delegateMethod.Invoke();
100         }
101 
102 
103         public delegate void VoidNoParamsMethod();
104     }

--------------------------------------------------------------------------

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             TestClass testClass = new TestClass();
 6             testClass.Age = 1234;
 7             int age = testClass.Age;
 8             Console.WriteLine(age);
 9         }
10 
11 
12          
13     }
14 
15     public class TestClass
16     {
17         public int Age;
18     }

对应的 ILGenerator.Emit 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5 //.method private hidebysig static void  Main(string[] args) cil managed
 6 //{
 7 //  .entrypoint
 8 //  // 代码大小       33 (0x21)
 9 //  .maxstack  2
10 //  .locals init ([0] class ComplexSetValue.TestClass testClass,
11 //           [1] int32 age)
12 //  IL_0000:  nop
13 //  IL_0001:  newobj     instance void ComplexSetValue.TestClass::.ctor()
14 //  IL_0006:  stloc.0
15 //  IL_0007:  ldloc.0
16 //  IL_0008:  ldc.i4     0x4d2
17 //  IL_000d:  stfld      int32 ComplexSetValue.TestClass::Age
18 //  IL_0012:  ldloc.0
19 //  IL_0013:  ldfld      int32 ComplexSetValue.TestClass::Age
20 //  IL_0018:  stloc.1
21 //  IL_0019:  ldloc.1
22 //  IL_001a:  call       void [mscorlib]System.Console::WriteLine(int32)
23 //  IL_001f:  nop
24 //  IL_0020:  ret
25 //} // end of method Program::Main
26 
27             DynamicMethod dm = new DynamicMethod("SetValueMethod", null, new Type[] { /*typeof(object), typeof(object)*/ }, true);
28 
29             ILGenerator generator = dm.GetILGenerator();
30 
31             generator.DeclareLocal(typeof(TestClass));  //声明变量
32             generator.DeclareLocal(typeof(int));  //声明变量
33 
34             //加载参数1,需要注意的是静态方法Ldarg_0对应的是参数1,
35             //实例方法Ldarg_0对应的是this指针,Ldarg_1对应的是参数1,
36             //即每个实例方法都传递一个隐含的this指针
37 
38             //TestClass testClass = new TestClass();
39             //testClass.Age = 1234;
40             //int age = testClass.Age;
41             //Console.WriteLine(age);
42 
43             //TestClass testClass = new TestClass();
44             //newobj     instance void ComplexSetValue.TestClass::.ctor()
45             ConstructorInfo testClassConstructor = typeof (TestClass).GetConstructor(new Type[] {});
46             generator.Emit(OpCodes.Newobj, testClassConstructor);
47             generator.Emit(OpCodes.Stloc_0);
48 
49             //testClass.Age = 1234;
50             //ldloc.0
51             //ldc.i4     0x4d2  //1234
52             //stfld      int32 ComplexSetValue.TestClass::Age
53             generator.Emit(OpCodes.Ldloc_0);
54             generator.Emit(OpCodes.Ldc_I4, 1234);
55             FieldInfo fieldInfo = typeof (TestClass).GetField("Age");
56             generator.Emit(OpCodes.Stfld, fieldInfo);
57 
58             //int age = testClass.Age;
59             //ldloc.0
60             //ldfld      int32 ComplexSetValue.TestClass::Age
61             //stloc.1
62             generator.Emit(OpCodes.Ldloc_0);
63             generator.Emit(OpCodes.Ldfld, fieldInfo);
64             generator.Emit(OpCodes.Stloc_1);
65 
66             //Console.WriteLine(age);
67             //ldloc.0
68             //call       void [mscorlib]System.Console::WriteLine(object)
69             generator.Emit(OpCodes.Ldloc_1);
70             MethodInfo writeLineMethodInfo = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
71             generator.Emit(OpCodes.Call, writeLineMethodInfo);
72             //generator.EmitCall(OpCodes.Call, writeLineMethodInfo, null);   //和上面代码 同意思
73 
74             //generator.Emit(OpCodes.Pop);   //是否是 无返回值函数 调用之后,不用弹出堆栈?
75 
76             //return
77             generator.Emit(OpCodes.Ret);   //函数执行完成
78 
79 
80             //将函数作为 委托
81             VoidNoParamsMethod delegateMethod = (VoidNoParamsMethod)dm.CreateDelegate(typeof(VoidNoParamsMethod));
82             //执行委托
83             delegateMethod.Invoke();
84         }
85     }
86 
87     public delegate void VoidNoParamsMethod();
88 
89     public class TestClass
90     {
91         public int Age;
92     }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【类型转换】使用c#实现简易的类型转换(Emit,Expression,反射)
    哈喽。大家好,好久不见,最近遇到了一个场景,就是在FrameWork的asp.net mvc中,有个系统里面使用的是EntityFramework的框架,在这个框架里,提供了一个SqlQuery的方法,这个方法很好用啊,以至于在EFCORE8里面又添加了回来,不过不知道性能怎么样,我遇到的场景是通过SqlQuery查询的时候,转换很慢,我估计那背后大概率是使用反射造成的, 因为我的查询可能有上十万,甚至更多,就导致了这个转换的过程及其耗时,以至于刚开始我是想通过Emit等方式去实现一个高性能转换,可是到最后没有去弄,因为我用了DataCommand去查询,最后循环DataReader来实现硬赋值,这样性能是最好,一下减少了好多秒,提升了80%,但也给了我一个灵感,一个实现简易的类型转换的灵感,所以在上周我就把代码写了出来,不过由于工作的忙碌,今天才开始写博客,接下来就呈上。
陈显达
2023/12/29
3610
晚绑定场景下对象属性赋值和取值可以不需要PropertyInfo
在《一句代码实现批量数据绑定》中,我通过界面控件ID与作为数据源的实体属性名之间的映射实现了批量数据绑定。由于里面频繁涉及对属性的反射——通过反射从实体对象中获取某个属性值;通过反射为控件的某个属性赋值,所以这不是一种高效的操作方式。为了提升性能,我通过IL Emit的方式创建了一个PropertyAccessor组件,以实现高效的属性操作。如果你看了我在文中给出的三种属性操作性能的测试结果,相信会对PropertyAccessor的作用有深刻的印象。[源代码从这里下载] 目录: 一、Prop
蒋金楠
2018/02/07
8650
晚绑定场景下对象属性赋值和取值可以不需要PropertyInfo
IL合集
    由于之前写的表达式树合集,未编写任何注释且是以图片的形式展现给大家,在这里向各位看官道歉了,接下来为大家奉上新鲜出炉的香喷喷的IL合集,后面会持续更新,各位看官点关注不迷路,之前答应的手写IOC以及多线程合集,目前IOC方面的困难已经解决掉,就差怎么封装了,有想法的看官可以加QQ群6406277,四川观察就是我,多线程方面的后面demo写出来整理好之后,届时会为大家奉上。,IL合集中注释已经写清楚,不明白可以在群里找我,好了,不多啰嗦,正文开始。
陈显达
2022/11/07
2610
.NET IL实现对象深拷贝
对于深拷贝,通常的方法是将对象进行序列化,然后再反序化成为另一个对象。例如在stackoverflow上有这样的解决办法:https://stackoverflow.com/questions/78536/deep-cloning-objects/78612#78612。这种序列化的方式,对深拷贝来讲,无疑是一个性能杀手。
郑子铭
2023/08/29
3260
.NET IL实现对象深拷贝
推荐一个快速反射调用的类
使用传统的.net反射机制,调用类的方法时,在调用频率大的情况下,会感觉速度很慢。最近浏览卢彦的博客时,找到一个他改进后的反射调用类。试用以后感觉效率明显提高,特推荐给大家。作者重新实现了,反射调用方法,但是调用接口和.net原有方法一致。而且调用时抛出的异常为所调用类的实际异常,不像传统方式返回为包装异常。 文章来源:http://www.codeproject.com/csharp/FastMethodInvoker.asp 快速反射调用类
跟着阿笨一起玩NET
2018/09/18
5470
C# 使用Emit深克隆
有人问,复制一个类所有属性到另一个类有多少方法?这也就是问深克隆有多少个方法,容易想的有三个。直接复制,反射复制,序列化复制。但是性能比较快的有表达式树复制 IL复制两个,本文主要讲最后一个
林德熙
2022/08/04
5480
C# 使用Emit深克隆
有人问,复制一个类所有属性到另一个类有多少方法?这也就是问深克隆有多少个方法,容易想的有三个。直接复制,反射复制,序列化复制。但是性能比较快的有表达式树复制 IL复制两个,本文主要讲最后一个
林德熙
2018/09/18
1K0
C# 使用Emit深克隆
c#通过Emit方式实现动态代理
之前自己在写一个IOC小轮子的时候,临时想加一个动态代理拦截功能,考虑到实用性方面,使用了Emit动态生成的方式代替RealProxy加反射的实现,网上查找过不少版本,但是都存在一些缺陷,所以决定自己实现一个。
code2roc
2023/07/19
4680
30分钟?不需要,轻松读懂IL
先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用。到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西。最重要的理由就是一个
用户1147588
2018/01/04
8640
30分钟?不需要,轻松读懂IL
NetCore实现Transitional自定义注解事物
之前实现了NetCore实现自定义IOC容器注入,在Controller使用事物的过程中思考是否能够像Spring一样通过自定义注解实现事物管理,思路图如下
code2roc
2023/07/19
2690
NetCore实现Transitional自定义注解事物
关于Expression Tree和IL Emit的所谓的"性能差别"
昨天写了《三种属性操作性能比较》,有个网友写信问我一个问题:从性能上看,Expression Tree和IL Emit孰优孰劣?虽然我在回信中作了简单的回答,但不知道这个网友是否懂我的意思。反正今天呆
蒋金楠
2018/02/08
9330
【.NET8】访问私有成员新姿势UnsafeAccessor(下)
书接上回,我们讨论了在.NET8中新增的 UnsafeAccessor,并且通过 UnsafeAccessor访问了私有成员,这极大的方便了我们代码的编写,当然也聊到了它当前存在的一些局限性,那么它的性能到底如何?我们今天就来实际测试一下。
InCerry
2023/09/21
5130
【.NET8】访问私有成员新姿势UnsafeAccessor(下)
C# 反射与特性(十):EMIT 构建代码
前面,本系列一共写了 九 篇关于反射和特性相关的文章,讲解了如何从程序集中通过反射将信息解析出来,以及实例化类型。
痴者工良
2021/04/26
8060
[C#3] 1-扩展方法
1.从DEMO开始 先看一个扩展方法的例子: 1 class Program 2 { 3 public static void Main() 4 { 5 Int32 myNum = 1; 6 myNum = myNum.AddToOldNum(1); 7 Console.WriteLine(myNum); 8 } 9 } 10 11 public static clas
blackheart
2018/01/19
6610
AssemblyBuilder以及Activator双剑合璧
AssemblyBuilder和Activator两个类是DispatchProxy类实现动态代理以及AOP的根本,示例demo可参考 DispatchProxy实现动态代理及AOP 。AssemblyBuilder的命名空间是System.Reflection.Emit,没错就是你听过的Emit。那么它是干什么用的?先看看 官方 的示例代码:
Ryan_OVO
2023/10/19
1400
AssemblyBuilder以及Activator双剑合璧
C#动态方法拦截(AOP)的5种解决方案!
AOP的本质是方法拦截(将针对目标方法调用劫持下来,进而执行执行的操作),置于方法拦截的实现方案,不外乎两种代码注入类型,即编译时的静态注入和运行时的动态注入,本篇文章列出了几种常用的动态注入方案。
郑子铭
2023/09/19
1.3K0
C#动态方法拦截(AOP)的5种解决方案!
.NET高级特性-Emit
在这个大数据/云计算/人工智能研发普及的时代,Python的崛起以及Javascript的前后端的侵略,程序员与企业似乎越来越青睐动态语言所带来的便捷性与高效性,即使静态语言在性能,错误检查等方面的优于静态语言。
李明成
2020/02/12
1.1K0
【深入浅出.Net IL】1.一个For循环引发的IL
1.准备工作 (1)新建一个project using System; namespace newArr { class Program { static void Main(string[] args) { char[] arrchars = new char[5]; for (int i = 0; i < 5; i++) { arrchars[i] =
悟空聊架构
2018/05/18
6310
来一点反射和Emit,让ORM的使用极度简化
PDF.NET开发框架一直是号称“无需反射”的,因为它的ORM框架(PDF.NET不仅仅是一个ORM框架,详细请见官网)中实体类的设计很特别,不需要反射就能够获知映射的字段信息,我们用实际的例子来说明
用户1177503
2018/02/27
9980
来一点反射和Emit,让ORM的使用极度简化
从 “x is null 和 x == null” 的区别看 C# 7 模式匹配中常量和 null 的匹配
发布于 2017-11-06 15:24 更新于 2018-02-19 22:39
walterlv
2018/09/18
1.4K0
相关推荐
【类型转换】使用c#实现简易的类型转换(Emit,Expression,反射)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验