引言

在第一篇关于IL的文章中,我们写了一些IL的相加,创建对象,循环以及实现TryCatch的一些功能,接下来,为大家带上后续关于IL的更新,其中包括,类型转换,以及条件判断,还有定义字段,定义属性,定义事件,以及事件能够实现多播委托的功能,最后还有定义枚举。

类型转换

var methodBydy = typeBulder.DefineMethod("Box", MethodAttributes.Public, CallingConventions.Standard, typeof(object), new Type[] { typeof(int) });
var ilMethod = methodBydy.GetILGenerator();
ilMethod.Emit(OpCodes.Nop);//不做任何操作
ilMethod.Emit(OpCodes.Ldarg_1);//加载第一个参数到堆栈
ilMethod.Emit(OpCodes.Box, typeof(int));//将int类型转为引用类型并且推送到计算机堆栈
ilMethod.Emit(OpCodes.Ret);//返回栈顶结果

上面的代码是将值类型转为引用类型,并且返回结果。

逻辑判断

Brtrue

 var methods = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });//输出字符串
var method = typeBulder.DefineMethod("BrTrue", MethodAttributes.Public, CallingConventions.Standard, typeof(void), new Type[] { typeof(object) });
var il = method.GetILGenerator();
var trueLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Brtrue, trueLabel);//第一个参数不是0或者不是null,或者不是false则跳转到trueLabel标签
il.Emit(OpCodes.Ret);
il.MarkLabel(trueLabel);
il.Emit(OpCodes.Ldstr, "参数是没问题的");
il.Emit(OpCodes.Call, methods);//调用方法
il.Emit(OpCodes.Ret);

上面的代码中定义了一个方法,入参为object类型,在下面IL代码中是判断这个参数是否为null或者是0,如果不是 就跳转到truelabel标签代码,

Brfalse

 var methods = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });//输出字符串
var method = typeBulder.DefineMethod("Brfalse", MethodAttributes.Public, CallingConventions.Standard, typeof(void), new Type[] { typeof(object) });
var il = method.GetILGenerator();
var falseLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Brfalse, falseLabel);//第一个参数是0或者是null,或者是false则跳转到falseLabel标签
il.Emit(OpCodes.Ret);
il.MarkLabel(falseLabel);
il.Emit(OpCodes.Ldstr, "参数是false,或者0,或者空引用");
il.Emit(OpCodes.Call, methods);//调用方法
il.Emit(OpCodes.Ret);

与上面的相反,Brfalse是判断参数是否为空引用或者null或者是0;

定义字段,属性,赋值

  var field = typeBulder.DefineField("customField", typeof(int), FieldAttributes.Private);//定义字段
var proper = typeBulder.DefineProperty("CustomField", PropertyAttributes.None, typeof(int), null);//定义属性
var getMethod = typeBulder.DefineMethod("get_CustomField", MethodAttributes.Public, typeof(int), Type.EmptyTypes);//属性的Get方法 就是Get关键字
var setMethod = typeBulder.DefineMethod("set_CustomField", MethodAttributes.Public, null, new Type[] { typeof(int) });//属性的Set方法 就是Set关键字
var getIl = getMethod.GetILGenerator();//构造get方法体
getIl.Emit(OpCodes.Ldarg_0);//加载自变量
getIl.Emit(OpCodes.Ldfld, field);//看清楚是Ldfld,load field 不是 ldsfld load static field //将Field字段加载到堆栈
getIl.Emit(OpCodes.Ret);//返回栈顶的field
var setIl = setMethod.GetILGenerator();//构造set方法体
setIl.Emit(OpCodes.Ldarg_0);//加载自变量
setIl.Emit(OpCodes.Ldarg_1);//拿到第一个参数
setIl.Emit(OpCodes.Stfld, field);//给field赋值
setIl.Emit(OpCodes.Ret);//返回方法
proper.SetGetMethod(getMethod);//设置属性的get方法
proper.SetSetMethod(setMethod);//设置属性的set方法
var getmh = typeBulder.DefineMethod("GetCustomField", MethodAttributes.Public, typeof(int), Type.EmptyTypes);//写一个获取属性的方法
var ilMh = getmh.GetILGenerator();
ilMh.Emit(OpCodes.Nop);
ilMh.Emit(OpCodes.Ldarg_0);//加载自变量
ilMh.Emit(OpCodes.Call, proper.GetMethod);//调用属性的get方法
ilMh.Emit(OpCodes.Ret);//并且返回
var setmh = typeBulder.DefineMethod("SetCustomField", MethodAttributes.Public, null, new Type[] { typeof(int) });//写一个设置属性的方法
var setMhIl = setmh.GetILGenerator();
setMhIl.Emit(OpCodes.Nop);//
setMhIl.Emit(OpCodes.Ldarg_0);//加载自变量
setMhIl.Emit(OpCodes.Ldarg_1);//获取第一个参数
setMhIl.Emit(OpCodes.Call, proper.SetMethod);//将第一个参数传给set方法赋值
setMhIl.Emit(OpCodes.Ret);//返回

在C#中,由于编辑器对代码进行了封装所以,我们定义属性的时候,是使用get set关键字去进行设置的,但是实际上get和set也是方法,在很久之前的版本记得是1.0的时候是没有这两个关键字的,当时定义属性是和Java一样需要定义get set方法,所以上面那段代码,定义了一个属性叫CustomField,那对应的属性需要有get和set方法,那在get方法,只需要返回定义的字段信息,然后返回就可以了,在set方法中,只需要把参数赋值给定义的字段,就是先set方法。

定义事件以及实现多播

 var invokeMethod = typeof(Action<string>).GetMethod("Invoke");
var eventField = typeBulder.DefineField("onChange", typeof(Action<string>), FieldAttributes.Private);//定义字段
var eventProper = typeBulder.DefineEvent("OnChange", EventAttributes.None, typeof(Action<string>));//定义event
var addMethod = typeBulder.DefineMethod("AddEvent", MethodAttributes.Public, null, new Type[] { typeof(Action<string>) });//定义event的add方法 关键字add
var ilAdd = addMethod.GetILGenerator();
ilAdd.Emit(OpCodes.Ldarg_0);//加载自变量
ilAdd.Emit(OpCodes.Ldarg_1);//第一个参数加载到堆栈
ilAdd.Emit(OpCodes.Stfld, eventField);//给字段赋值
ilAdd.Emit(OpCodes.Ret);//返回
eventProper.SetAddOnMethod(addMethod);//将set方法添加到属性
var removeMethod = typeBulder.DefineMethod("RemoveEvent", MethodAttributes.Public, null, new Type[] { typeof(Action<string>) });//定义event的remove方法,关键字remove
var ilRemove = removeMethod.GetILGenerator();
ilRemove.Emit(OpCodes.Ldarg_0);//加载自变量
ilRemove.Emit(OpCodes.Ldarg_1);//第一个参数加载到堆栈
ilRemove.Emit(OpCodes.Stfld, eventField);//给字段赋值
ilRemove.Emit(OpCodes.Ret);
eventProper.SetRemoveOnMethod(removeMethod);//将remove方法添加到属性
var raiseMh = typeBulder.DefineMethod("RaiseMethod", MethodAttributes.Public, null, Type.EmptyTypes);//定义触发事件的方法
var raiseIl = raiseMh.GetILGenerator();
raiseIl.Emit(OpCodes.Ldarg_0);//加载自变量
raiseIl.Emit(OpCodes.Ldfld, eventField);//加载字段到堆栈
raiseIl.Emit(OpCodes.Ldstr, "Hello World!");//加载字符串参数到堆栈,
raiseIl.Emit(OpCodes.Callvirt, invokeMethod);//将helloworld传入方法
raiseIl.Emit(OpCodes.Ret);//结束方法
eventProper.SetRaiseMethod(raiseMh);
var type = typeBulder.CreateType();
var instance = Activator.CreateInstance(type);
var events = type.GetEvent("OnChange"); var action = new Action<string>(s =>
{
Console.WriteLine(s);//输出上方的helloworld
});
events.AddEventHandler(instance, action);
events.RaiseMethod.Invoke(instance, new object[] { });
events.RemoveEventHandler(instance, null);

众所周知,事件是可以定义成委托类型,委托又涉及到了多播委托,这里不对反编译后的委托进行过多的讲解,只是通过Delegate的combine方法进行多个委托的连接从而实现一个多播委托,并且定义相关的add和remove的方法,以及触发事件的方法

枚举

 var em = moduleBulder.DefineEnum("LoginType", TypeAttributes.Public, typeof(int));
em.DefineLiteral("UserPassWordType", 0);
em.DefineLiteral("Other", 1);

枚举的定义其实很简单,可以看一下上面的代码。

结语

今天的IL合集就到这里了,具体的项目中使用还是得结合具体的场景去实现。

Box 值类型转引用类型

IL合集二的更多相关文章

  1. IL合集

    由于之前写的表达式树合集,未编写任何注释且是以图片的形式展现给大家,在这里向各位看官道歉了,接下来为大家奉上新鲜出炉的香喷喷的IL合集,后面会持续更新,各位看官点关注不迷路,之前答应的手写IOC以及多 ...

  2. 史上最全最新java面试题合集二(附答案)

    下面小编整理了本套java面试题全集,分享给大家,希望对大家的java学习和就业面试有所帮助. 51.类ExampleA继承Exception,类ExampleB继承ExampleA. 有如下代码片断 ...

  3. Java面试题合集(二)

    接下来几篇文章准备系统整理一下有关Java的面试题,分为基础篇,javaweb篇,框架篇,数据库篇,多线程篇,并发篇,算法篇等等,陆续更新中.其他方面如前端后端等等的面试题也在整理中,都会有的. 注: ...

  4. 多线程合集(二)---异步的那些事,async和await原理抛析

    引言 在c#中,异步的async和await原理,以及运行机制,可以说是老生常谈,经常在各个群里看到有在讨论这个的,而且网上看到的也只是对异步状态机的一些讲解,甚至很多人说异步状态机的时候,他们说的是 ...

  5. php大力力 [025节] 来不及学习和分类的,大力力认为有价值的一些技术文章合集(大力力二叔公)(2015-08-27)

    php大力力 [025节] 来不及学习和分类的,大力力认为有价值的一些技术文章合集(大力力二叔公)(2015-08-27) 比较好的模版 免费模板网,提供大量DIV+CSS布局网页模板下载及后台管理 ...

  6. 【转】Reflector、reflexil、De4Dot、IL相关操作指令合集

    PS:CTRL+F 输入你需要的内容,可以快速查找页面上的内容. 名称 说明 Add 将两个值相加并将结果推送到计算堆栈上. Add.Ovf 将两个整数相加,执行溢出检查,并且将结果推送到计算堆栈上. ...

  7. SQL用法操作合集

    SQL用法操作合集   一.表的创建 1.创建表 格式: 1 CREATE TABLE 表名 2 (列名 数据类型(宽度)[DEFAULT 表达式][COLUMN CONSTRAINT], 3 ... ...

  8. android 图像处理系列合集

    为了便于大家对滤镜算法的学习,以后发布的图像处理滤镜系列帖子会在这里汇总,本人第一次写合集,写得不好的地方大家请见谅,手头上虽然有一些滤镜的算法,但是大多不是android版的,教程里的代码大多是我借 ...

  9. 【收藏】Java多线程/并发编程大合集

    (一).[Java并发编程]并发编程大合集-兰亭风雨    [Java并发编程]实现多线程的两种方法    [Java并发编程]线程的中断    [Java并发编程]正确挂起.恢复.终止线程    [ ...

  10. Python之路【第二十四篇】:Python学习路径及练手项目合集

      Python学习路径及练手项目合集 Wayne Shi· 2 个月前 参照:https://zhuanlan.zhihu.com/p/23561159 更多文章欢迎关注专栏:学习编程. 本系列Py ...

随机推荐

  1. ElasticSearch之Delete index API

    删除指定的索引. 同时删除索引关联的数据.分片.元数据等相关的资源,因此执行前需要慎重. 命令样例如下: curl -X DELETE "https://localhost:9200/tes ...

  2. 从零玩转第三方登录之WeChat公众号登陆-cong-ling-wan-zhuan-di-san-fang-deng-lu-zhi-wechat-gong-zhong-hao-deng-lu

    title: 从零玩转第三方登录之WeChat公众号登陆 date: 2022-09-03 16:32:57.876 updated: 2022-09-03 16:32:57.876 url: htt ...

  3. JavaFx 打包jar(六)

    JavaFx 打包jar(六) JavaFX 从入门入门到入土系列 我们编写了不少javafx,那么如何打包成jar给用户呢?下面我给出比较全的打包方式. 打包jar 下面我给出比较全的打包方式. 1 ...

  4. Spring Cloud(一)Eureka

    单体应用存在的问题 在传统应用程序中,一般都会将整个的应用程序作为一个单独的可执行文件部署到相应的服务器上执行.一般的应用程序结构可能如下图所示: 这种方式的优点很明显,比如:架构简单,服务之间调用逻 ...

  5. GaussDB(DWS)性能调优:Sort+Groupagg聚集引起的性能瓶颈案例

    本文分享自华为云社区<GaussDB(DWS)性能调优:Sort+Groupagg聚集引起的性能瓶颈案例>,作者: O泡果奶~ . 本文针对SQL语句长时间执行不出来,且verbose执行 ...

  6. 看完这篇,DWS故障修复不再愁

    摘要:本文详细梳理分析了DWS服务面临软硬件故障场景和对应的修复原理,希望借此能够让你对DWS的集群故障修复有个全面深入的了解. 本文分享自华为云社区<GaussDB(DWS)故障修复系统性介绍 ...

  7. 详解JQuery框架的五大选择器

    摘要:今天来和大家分享一下JQuery的五种选择器的详细使用方法. 本文分享自华为云社区<[JQuery框架]五大选择器"全家桶"详解!!!>,原文作者:灰小猿 . 今 ...

  8. 鸿蒙轻内核源码分析:MMU协处理器

    摘要:本系列首先了解下ARM CP15协处理器的知识,接着介绍下协处理器相关的汇编指令,最后分析下MMU相关汇编代码. 本文分享自华为云社区<鸿蒙轻内核A核源码分析系列六 MMU协处理器> ...

  9. 再谈BOM和DOM(3):DOM节点操作-元素样式修改及DOM内容增删改查

    操作节点,先得选择节点,就得知道节点选择器与DOM节点查找 DOM节点选择器 W3C提供了比较方便的定位节点的方法和属性 getElementById() 一个参数:元素标签的ID getElemen ...

  10. APP加固原理与作用

    APP加固原理与作用 引言 在移动应用开发中,APP加固是一种保护应用代码逻辑的重要措施.通过对应用文件进行隐藏.混淆和加密等操作,可以有效提高软件的逆向成本,降低被破解的几率.本文将介绍APP加固的 ...