- 浏览: 222831 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
zhangwei412827_:
[flash=200,200][/flash]
js 关键字 in 的使用方法 -
flycatdeng:
.classpath文件在哪里?
AndEngine示例运行环境搭建过程 -
revol:
请问,你是如何调用LSMessage,并弹出窗口的?
Silverlight模拟MSN和QQ即时提示消息框
---------------------------------------------------------------------------------------------------
例子 1: 最简单的语句
public void Test1() { Console.WriteLine("aaaa"); }
生成的IL:
.method public hidebysig instance void Test1() cil managed { .maxstack 8 L_0000: nop L_0001: ldstr "aaaa" L_0006: call void [mscorlib]System.Console::WriteLine(string) L_000b: nop L_000c: ret }
使用ILGenerator的Emit方法,改写为
ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldstr, "aaaa"); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret);
---------------------------------------------------------------------------------------------------
例子 2
public void Test1() { string str = "aaaa"; Console.WriteLine(str); }
生成的IL:
.method public hidebysig instance void Test1() cil managed { .maxstack 1 .locals init ( [0] string str) L_0000: nop L_0001: ldstr "aaaa" L_0006: stloc.0 L_0007: ldloc.0 L_0008: call void [mscorlib]System.Console::WriteLine(string) L_000d: nop L_000e: ret }
使用ILGenerator的Emit方法,改写为:
var str = il.DeclareLocal(typeof(string)); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldstr, "aaaa"); il.Emit(OpCodes.Stloc, str); il.Emit(OpCodes.Ldloc, str); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret);
---------------------------------------------------------------------------------------------------
例子 3 : 运算
public void PrintCube(int i) { int cube = i * i * i; Console.WriteLine(cube); }
生成的IL:
.method public hidebysig instance void PrintCube(int32 i) cil managed { .maxstack 2 // 在 .locals 部分声明所有的局部变量。 .locals init ( [0] int32 cube) // 第一个名局部变量,int 型,名为 cube。索引从 0 开始。 L_0000: nop // no operation. L_0001: ldarg.1 // load argument 第一个方法参数入栈,比如“3”。索引号 从 1 开始,而不是从 0 开始。 L_0002: ldarg.1 // 再次向堆栈压入第一个方法参数,又一个“3”。 L_0003: mul // multiply 计算堆栈最顶上两个数的乘积 3×3,并把结果入栈,即堆栈最顶部是 9 了。 L_0004: ldarg.1 // 再次压入第一个方法参数“3”。 L_0005: mul // 堆栈最顶上是“3”,第二是“9”,计算 3×9,此时 27 入栈。 L_0006: stloc.0 // pop value from stack to local variable 堆栈最顶上的值“27”出栈, //并被赋给索引位置“0”处的局部变量 cube,即内存中变量 cube 的值为“27”。 L_0007: ldloc.0 // 局部变量 cube 的值“27”入栈。 L_0008: call void [mscorlib]System.Console::WriteLine(int32) // 控制台输出堆栈最顶上的32 位整数“27”。 L_000d: nop // no operation. L_000e: ret // return from method. }
使用ILGenerator的Emit方法,改写为:
ILGenerator il = methodBuilder.GetILGenerator(); var cube = il.DeclareLocal(typeof(int)); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) })); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret);
---------------------------------------------------------------------------------------------------
例子 4 : 循环语句
public void SeparateString(string source) { if (source == null) return; int count = source.Length; char c; for (int i = 0; i < count; i++) { c = source[i]; Console.WriteLine(c); } }
生成的IL:
.method public hidebysig instance void SeparateString(string source) cil managed { .maxstack 2 .locals init ( [0] int32 count, [1] char c, [2] int32 i, [3] bool CS$4$0000) // 索引为“3”的这个布尔型局部变量在 C# 代码中并未显式声明,是编译器编译时添加的, //用于保存执行过程中布尔运算的结果,比如比较 source 是否为空时,以及比较 i<count 时。 L_0000: nop L_0001: ldarg.1 // 方法参数 source 的值入栈。 L_0002: ldnull // “空引用”null入栈。 L_0003: ceq // compare equal 比较栈顶的 null 和第二项的 source 是否相等,并 // 把结果 0(false,source 不为空)或 1(true,source 为空)入栈。 L_0005: ldc.i4.0 // 32 位整型数“0”入栈。 L_0006: ceq // 比较栈顶的“0”和堆栈的第二项,第二项可能是“0”,也可能 // 是“1”。比较的结果“1”或“0”入栈。 L_0008: stloc.3 // 栈顶的“1”或“0”出栈,被保存到索引为“3”的局部变量中。 L_0009: ldloc.3 // 执行后,栈顶为“1”(source 不为空)或“0”(source 为空)。 L_000a: brtrue.s L_000e // branch on non-false or non-null 判断栈顶是否 // 为“1”,如果是,跳转到第“IL_000e”行;否则继续往下执行。 L_000c: br.s L_0036 // unconditional branch 当栈顶为“0”时,才会 // 执行到这一行,这一行的执行结果是程序无条件 // 跳转到第“IL_0036”行。 L_000e: ldarg.1 L_000f: callvirt instance int32 [mscorlib]System.String::get_Length() // 对堆栈最顶上的字符串调用其获取长度的实例方法,长度值被入栈。 // “get_Length()”实际是字符串 Length 属性的“get”部分。 L_0014: stloc.0 // 局部变量 count 被赋值为字符串长度。 L_0015: ldc.i4.0 L_0016: stloc.2 // 局部变量 i 被赋值为 0。 L_0017: br.s L_002e // 无条件跳转到第“IL_002e”行。 L_0019: nop L_001a: ldarg.1 L_001b: ldloc.2 L_001c: callvirt instance char [mscorlib]System.String::get_Chars(int32) // source 中索引为 i 处的 char 值入栈。 L_0021: stloc.1 L_0022: ldloc.1 L_0023: call void [mscorlib]System.Console::WriteLine(char) // char 值被输出到控制台 L_0028: nop L_0029: nop L_002a: ldloc.2 // i 值入栈。 L_002b: ldc.i4.1 // 32 位整数 1 入栈。 L_002c: add // i+1 的结果入栈。 L_002d: stloc.2 // i=i+1。 L_002e: ldloc.2 // i 值入栈。 L_002f: ldloc.0 // count 值入栈。 L_0030: clt // compare less than 比较 i<count 是否为真,比较结果入栈。 L_0032: stloc.3 L_0033: ldloc.3 L_0034: brtrue.s L_0019 // 如果 i<count 则跳转到第“IL_0019”行。 L_0036: ret }
---------------------------------------------------------------------------------------------------
例子 5 : 基本类型
public void SayHello(string toWhom) { int i = 1000; double d = 3.1; float f = 4.2F; Console.WriteLine(i); Console.WriteLine(d); Console.WriteLine(f); }
生成的IL:
.method public hidebysig newslot virtual final instance void SayHello(string toWhom) cil managed { .maxstack 1 .locals init ( [0] int32 i, [1] float64 d, [2] float32 f) L_0000: nop L_0001: ldc.i4 1000 L_0002: stloc.0 L_0003: ldc.r8 3.1 L_000c: stloc.1 L_000d: ldc.r4 4.2 L_0012: stloc.2 L_0013: ldloc.0 L_0014: call void [mscorlib]System.Console::WriteLine(int32) L_0019: nop L_001a: ldloc.1 L_001b: call void [mscorlib]System.Console::WriteLine(float64) L_0020: nop L_0021: ldloc.2 L_0022: call void [mscorlib]System.Console::WriteLine(float32) L_0027: nop L_0028: ret }
---------------------------------------------------------------------------------------------------
例子 5 : if语句
int i = 1; if (i > 1) { Console.WriteLine("i > 1"); } else if (i == 1) { Console.WriteLine("i == 1"); } else { Console.WriteLine("i < 1"); }
生成的IL:
.maxstack 2 .locals init ( [0] int32 i, [1] bool CS$4$0000) L_0000: nop L_0001: ldc.i4.1 L_0002: stloc.0 L_0003: ldloc.0 L_0004: ldc.i4.1 L_0005: cgt L_0007: ldc.i4.0 L_0008: ceq L_000a: stloc.1 L_000b: ldloc.1 L_000c: brtrue.s L_001d L_000e: nop L_000f: ldstr "i > 1" L_0014: call void [mscorlib]System.Console::WriteLine(string) L_0019: nop L_001a: nop L_001b: br.s L_0044 L_001d: ldloc.0 L_001e: ldc.i4.1 L_001f: ceq L_0021: ldc.i4.0 L_0022: ceq L_0024: stloc.1 L_0025: ldloc.1 L_0026: brtrue.s L_0037 L_0028: nop L_0029: ldstr "i == 1" L_002e: call void [mscorlib]System.Console::WriteLine(string) L_0033: nop L_0034: nop L_0035: br.s L_0044 L_0037: nop L_0038: ldstr "i < 1" L_003d: call void [mscorlib]System.Console::WriteLine(string) L_0042: nop L_0043: nop L_0044: ret
使用ILGenerator的Emit方法,改写为:
MethodBuilder methodBuilder = typeBuilder.DefineMethod("If", MethodAttributes.Public, typeof(void), null); ILGenerator il = methodBuilder.GetILGenerator(); var i = il.DeclareLocal(typeof(int)); var b = il.DeclareLocal(typeof(bool)); var lblElse = il.DefineLabel(); var lblElse2 = il.DefineLabel(); var lblEnd = il.DefineLabel(); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldc_I4_1); //取整数1,入栈 il.Emit(OpCodes.Stloc, i); //取栈中第一个值,赋值局部变量i il.Emit(OpCodes.Ldloc, i); //局部变量i入栈 il.Emit(OpCodes.Ldc_I4_1); //取整数1,入栈 il.Emit(OpCodes.Cgt); //取栈中前两个值,进行大于比较, //如果第一个值大于第二个值,则将整数值 1 (int32) 入栈;反之,将 0 (int32)入栈。 //此时的值为 1 il.Emit(OpCodes.Ldc_I4_0); //取整数0,入栈 il.Emit(OpCodes.Ceq); //取栈中前两个值,进行等于比较, //如果这两个值相等,则将整数值 1(int32)入栈;否则,将 0 (int32) 入栈 //此时的值为 0 il.Emit(OpCodes.Stloc, b); //取栈中第一个值,赋值局部变量b il.Emit(OpCodes.Ldloc, b); //局部变量b入栈 il.Emit(OpCodes.Brtrue_S, lblElse); //如果为真,控制流转到lblElse标签处,如果为假,继续下一条语句 il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldstr, "i > 1"); //引用字符串 il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //输出字符串 il.Emit(OpCodes.Nop); il.Emit(OpCodes.Br_S, lblEnd); il.MarkLabel(lblElse); //设定标签lblElse il.Emit(OpCodes.Ldloc, i); //局部变量i入栈 il.Emit(OpCodes.Ldc_I4_1); //取整数1,入栈 il.Emit(OpCodes.Ceq); //取栈中前两个值,进行等于比较 il.Emit(OpCodes.Ldc_I4_0); //取整数0,入栈 il.Emit(OpCodes.Ceq); //取栈中前两个值,进行等于比较 il.Emit(OpCodes.Stloc, b); //取栈中第一个值,赋值局部变量b il.Emit(OpCodes.Ldloc, b); //局部变量b入栈 il.Emit(OpCodes.Brtrue_S, lblElse2); //如果为真,控制流转到lblElse2标签处,如果为假,继续下一条语句 il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldstr, "i == 1"); //引用字符串 il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //输出字符串 il.Emit(OpCodes.Nop); il.Emit(OpCodes.Br_S, lblEnd); il.MarkLabel(lblElse2); //设定标签lblElse2 il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldstr, "i < 1"); //引用字符串 il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //输出字符串 il.Emit(OpCodes.Nop); il.MarkLabel(lblEnd); //设定标签lblEnd il.Emit(OpCodes.Ret);
---------------------------------------------------------------------------------------------------
测试完整代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Reflection.Emit; using System.Threading; namespace ILDemo { public class UserInfo { public void Test1() { Console.WriteLine("aaaa"); } /* 各种方法 */ } public class Program { public static void Main(string[] args) { AssemblyName asmName = new AssemblyName(); asmName.Name = "ILDemo"; AssemblyBuilder asmBuilder = Thread.GetDomain().DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("MyTestDemo"); TypeBuilder typeBuilder = modBuilder.DefineType( "UserInfo", TypeAttributes.Public, typeof(object), null); MethodBuilder methodBuilder = typeBuilder.DefineMethod("Test1", MethodAttributes.Public, typeof(void), null); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldstr, "aaaa"); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ret); /* 各种方法的Emit的实现 */ Type type = typeBuilder.CreateType(); object userInfo = Activator.CreateInstance(type); MethodInfo _MethodInfo = type.GetMethod("Test1"); _MethodInfo.Invoke(userInfo, null); Console.ReadKey(); } } }
发表评论
-
各种 Comet 技术优缺点对比
2015-12-15 09:16 527script tag iframe a ... -
Web 通信 之 长连接、长轮询(long polling)
2015-12-15 09:09 1014Web 通信 之 长连接、长轮询(long polling ... -
java并发编程不得不知道的几件事
2012-11-26 13:35 900多线程编程从来都是一件比较困难的事情,调试多线程程序也相当困难 ... -
C#正则表达式小结
2010-10-21 13:22 1016只能输入数字 ... -
常用正则表达式(整理中...)
2010-08-31 15:05 8441 提取中括号[]中内容 strin ... -
IL指令集——比较指令
2010-08-24 14:34 1091Public field Static Ceq ... -
IL指令集——跳转指令
2010-08-24 14:33 1690Public field Static Beq ... -
IL指令集——运算指令
2010-08-24 14:32 1258Public field Static Add ... -
Reflect中MethodInfo使用方法(整理中....)
2010-08-24 13:53 12339using System; using System.Col ... -
Emit学习之旅(2):创建常见元素—基础部分
2010-08-24 13:09 1680上回已经用Emit创建了一个简单的类型。下面接着说说如何为动态 ... -
Emit学习之旅(1):Emit概览
2010-08-24 13:03 1523转载Frog 博客空间:http://www.cnblogs ...
相关推荐
Emit学习之旅是一个深入探索C# Emit技术的教程,它为开发者提供了动态生成IL(Intermediate Language)代码的能力。Emit是.NET Framework的一部分,允许程序员在运行时构建和执行方法,这是实现元编程的重要工具。...
在Vue.js框架中,组件是构建可复用代码的基本单元,是 Vue 应用的核心组成部分。Vue组件可以被视为自定义HTML元素,它们有自己的属性、事件和生命周期方法,能够封装任何复杂的逻辑,使得代码结构清晰、易于维护。...
在PyQt编程中,信号和槽机制是核心概念之一,用于实现对象间的通信。当一个对象的状态发生改变时,它可以发出一个信号,其他对象可以通过连接这个信号来响应这个改变。在学习过程中,可能会遇到错误“AttributeError...
在这个例子中,`NavbarComponent`定义了一个名为`refreshEvent`的输出属性,并在按钮点击事件中触发该事件。父组件可以监听这个事件并执行相应的逻辑。 ##### 3. 服务(Services) 除了通过输入和输出进行组件间的...
Emit,全称为Event Emitter,是Node.js中的一个核心模块,它在JavaScript世界中扮演着事件驱动的重要角色。在本文中,我们将深入探讨Emit的相关知识点,包括其原理、用法以及在实际开发中的应用。 事件驱动是Node....
vnode.context.$emit('outside-click'); } }); }, unbind(el) { el.removeEventListener('click', () => {}); }, }, }, ``` 然后在父组件中监听这个事件,暂停自动切换: ```html ``` ```javascript ...
ILProperty文件中,第一个类 ILProperty 中void LdValue() 方法 50行:this.il.Emit(OpCodes.Ldnull); 改为一对大括号{} if (this.obj.GetGetMethod().IsStatic) this.il.Emit(OpCodes.Ldnull); else this.target....
Node.js的独特之处在于它完全拥抱JavaScript,不仅在服务器端代码中使用,还延伸至浏览器端,实现了真正的全栈JavaScript开发。此外,Node.js采用了基于异步I/O的并发模型,通过回调函数实现非阻塞操作,这使得Node....
emit@resource://devtools/shared/event-emitter.js:178:15 emit@resource://devtools/shared/event-emitter.js:255:5 setNodeFront@resource://devtools/client/framework/selection.js:153:5 onDetached@resource:...
emit.js JavaScript中的高效极简事件发射器。安装它可以与bower或npm一起使用: bower install emit.jsnpm install emit.js在HTML中包含emit.min.js ,并且在全局范围内现在可以使用emit对象: < script type =" ...
2. **Harold.Net.Emit.gpState** 这个文件可能是一个项目或库,其中包含关于如何使用EMIT来管理状态或执行特定任务的示例代码。gpState可能代表“通用程序状态”,它可能是用于演示如何动态生成处理状态变化的代码...
解决self.env.emit is not a function报错 报错内容 TypeError: self.env.emit is not a function at /usr/local/share/.config/yarn/global/node_modules/yeoman-generator/lib/index.js:653:22 at ...
socketIO.emit('your_event_name', {'data': 'hello world'}) ``` 5. **处理响应**:你可以注册回调函数来处理服务器发送的事件和数据。 ```python def on_message_received(*args): print('Received:', args...
4. **文件系统(fs)模块**:学习使用Node.js内置的fs模块进行文件操作,如读取、写入、创建、删除、重命名文件和目录。 5. **HTTP服务器**:构建简单的HTTP服务器,掌握`http`或`http2`模块的用法,实现接收请求并...
在Node.js项目中使用Socket.IO,首先需要安装它。安装命令如下: ```bash npm install socket.io ``` #### 三、使用Node.js HTTP服务器 ##### 1. 服务器端设置 ```javascript // 导入必要的模块 var app = require...
在微信小程序开发中,创建一个车牌号输入组件(虚拟键盘)是一项常见的需求,尤其是在交通、停车或汽车服务类的应用中。"carNumber.zip" 文件提供了一个实现这一功能的示例,帮助开发者创建一个用户友好且定制化的...
自定义事件:子组件可以通过 $emit 触发事件,父组件可以监听这些事件来执行操作。 3.Vuex:对于大型应用,Vuex 是一个状态管理模式和库,用于集中管理所有组件的公共状态。 4.插槽:Vue 允许你将父组件模板中的...
组件可以拥有自己的状态、方法和生命周期,也可以接收外部输入(props)和向父组件发出事件(emit)。在博客中可能涵盖如何创建、使用及优化组件的技巧。 3. **Vuex状态管理**:对于大型项目,Vuex是Vue官方推荐的...
在Vue.js的学习旅程中,组件化开发是其核心特性之一,极大地提高了代码的复用性和组织性。本篇文章将深入探讨Vue中的组件以及如何在组件间进行数据传递,旨在帮助初学者理解并掌握这一关键概念。 一、Vue组件 Vue...
总的来说,"Qt界面间互相通信.rar" 文件提供的示例是一个很好的学习资源,可以帮助开发者理解如何在Qt环境中实现窗口间通信,从而创建更加动态和交互性强的用户界面。通过熟练掌握这一技巧,你可以构建更复杂的应用...