IL合集
由于之前写的表达式树合集,未编写任何注释且是以图片的形式展现给大家,在这里向各位看官道歉了,接下来为大家奉上新鲜出炉的香喷喷的IL合集,后面会持续更新,各位看官点关注不迷路,之前答应的手写IOC以及多线程合集,目前IOC方面的困难已经解决掉,就差怎么封装了,有想法的看官可以加QQ群6406277,四川观察就是我,多线程方面的后面demo写出来整理好之后,届时会为大家奉上。,IL合集中注释已经写清楚,不明白可以在群里找我,好了,不多啰嗦,正文开始。
首先出场的是两数相加用IL实现
Add
#region Add { var methodAdd = typeBulder.DefineMethod("Add", MethodAttributes.Public, typeof(int), new Type[] { typeof(int), typeof(int) }); var ilMethod = methodAdd.GetILGenerator(); var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }); ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上 ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上 ilMethod.Emit(OpCodes.Add);//将第一个和第二个参数相加, ilMethod.Emit(OpCodes.Stloc_0);//结果赋值给第0个本地变量 ilMethod.Emit(OpCodes.Ldloc_0);//加载倒栈中 ilMethod.EmitCall(OpCodes.Call, method, new Type[] { typeof(int) });//输出 ilMethod.Emit(OpCodes.Ldloc_0);//加载 ilMethod.Emit(OpCodes.Ret);//返回相加后的结果 } #endregion
And
#region And { var methodAnd = typeBulder.DefineMethod("And", MethodAttributes.Public, typeof(int), new Type[] { typeof(int), typeof(int) }); var ilMethod = methodAnd.GetILGenerator(); var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }); ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上 ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上 ilMethod.Emit(OpCodes.And);//将第一个和第二个参数相加, ilMethod.Emit(OpCodes.Stloc_0);//将And结果 赋值给local ilMethod.Emit(OpCodes.Ldloc_0);//将Local推到栈 ilMethod.EmitCall(OpCodes.Call, method, new Type[] { typeof(int) }); ilMethod.Emit(OpCodes.Ldloc_0);////将Local推到栈 ilMethod.Emit(OpCodes.Ret);//返回And后的结果 } #endregion
ble bgt bge等比较大小相关的
#region Beq bgt bge ble blt { var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); var methodBeq = typeBulder.DefineMethod("Beq",MethodAttributes.Public,typeof(void),new Type[] { typeof(int),typeof(int)}); var ilMethod = methodBeq.GetILGenerator(); var labelEq = ilMethod.DefineLabel(); var labelNotEq= ilMethod.DefineLabel(); ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上 ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上 ilMethod.Emit(OpCodes.Beq, labelEq);//第一个和第二个是否相等 ilMethod.Emit(OpCodes.Ldarg_1);//取出方法的第一个参数 并加载到栈上 ilMethod.Emit(OpCodes.Ldarg_2);//取出方法的第二个参数 并加载到栈上 ilMethod.Emit(OpCodes.Bge, labelNotEq);//第一个是否大于等于第二个 可以自行更换为Bgt,ble blt ilMethod.Emit(OpCodes.Ret); ilMethod.MarkLabel(labelEq); ilMethod.Emit(OpCodes.Ldstr, "第一个数等于第二个数"); ilMethod.Emit(OpCodes.Call, method); ilMethod.Emit(OpCodes.Ret); ilMethod.MarkLabel(labelNotEq); ilMethod.Emit(OpCodes.Ldstr, "第一个数大于等于第二个数"); ilMethod.Emit(OpCodes.Call, method); ilMethod.Emit(OpCodes.Ret); } #endregion
IL构造循环代码
#region 循环 { var method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); var methodInt = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }); var methodXh = typeBulder.DefineMethod("Xunhuan", MethodAttributes.Public, typeof(void), new Type[] { }); var ilMethod = methodXh.GetILGenerator(); var localBegin=ilMethod.DeclareLocal(typeof(int));//定义循环开始变量 var localEnd= ilMethod.DeclareLocal(typeof(int));//结束变量 var labelXunhuan = ilMethod.DefineLabel();//定义循环主体 var labelEnd= ilMethod.DefineLabel();//定义结束标签主体 var labelBreak = ilMethod.DefineLabel();//定义中断标签 ilMethod.Emit(OpCodes.Ldc_I4, 0);//将0加载到栈上 ilMethod.Emit(OpCodes.Stloc_0);//这两句是给第0个局部变量赋值,0 ilMethod.Emit(OpCodes.Ldc_I4, 5);//将5加载到栈上 ilMethod.Emit(OpCodes.Stloc, 1);//这两句是给第1个局部变量赋值,5 ilMethod.Emit(OpCodes.Br, labelXunhuan);//无条件跳转到循环的label,即开始循环 ilMethod.MarkLabel(labelEnd);//标记这段代码是labelend的代码 ilMethod.Emit(OpCodes.Ldstr,"循环结束"); ilMethod.Emit(OpCodes.Call, method);//输出循环结束 ilMethod.Emit(OpCodes.Ret);//返回 ilMethod.MarkLabel(labelBreak); ilMethod.Emit(OpCodes.Ldstr, "循环终止"); ilMethod.Emit(OpCodes.Call, method);//输出循环结束 ilMethod.Emit(OpCodes.Break); ilMethod.Emit(OpCodes.Ret);//返回 ilMethod.MarkLabel(labelXunhuan);//标记是labelbegin的代码 ilMethod.Emit(OpCodes.Ldloc_0);//从栈中加载第0个局部变量 ilMethod.Emit(OpCodes.Ldloc_1);//从栈中加载第1个局部变量 ilMethod.Emit(OpCodes.Bge, labelEnd);//比较第0个是否小于等于第一个 ilMethod.Emit(OpCodes.Ldloc_0);//加载循环的第0变量 ilMethod.Emit(OpCodes.Call, methodInt);//打印出来 ilMethod.Emit(OpCodes.Ldc_I4,1);//将1加载到栈上 ilMethod.Emit(OpCodes.Ldloc_0);//从栈中加载第0个局部变量 ilMethod.Emit(OpCodes.Add);//相加 ilMethod.Emit(OpCodes.Stloc, 0);//结果赋值给本地0个局部变量 ilMethod.Emit(OpCodes.Ldc_I4, 3); ilMethod.Emit(OpCodes.Ldloc_0);//从栈中加载第0个局部变量 ilMethod.Emit(OpCodes.Beq, labelBreak);//比较第0个是否小于等于第一个 ilMethod.Emit(OpCodes.Br, labelXunhuan); } #endregion
IL构建对象
#region NewObj创建对象 { var conTest = typeof(TestNewobj).GetConstructors().FirstOrDefault(s => s.GetParameters().Length > 0); DynamicMethod dynamicMethod = new DynamicMethod("CreateInstance", typeof(TestNewobj), new Type[] { typeof(int), typeof(int) });//创建一个动态方法,方法名称,返回值,入参 var il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Nop);//不做操作 il.Emit(OpCodes.Ldarg_0);//从堆栈加载出方法的第0索引参数 il.Emit(OpCodes.Ldarg_1);//1索引参数 il.Emit(OpCodes.Newobj,conTest);//调用构造方法,并传入0,1索引参数的值 il.Emit(OpCodes.Ret);//返回创建的对象 var objCreator = dynamicMethod.CreateDelegate(typeof(Func<int,int, TestNewobj>)) as Func<int,int, TestNewobj>; var result = objCreator(5,10); var resu = result.Add(); } #endregion
IL实现TryCatch
#region Try Catch { var method = typeof(Console).GetMethod("WriteLine",new Type[] { typeof(string)});//输出字符串 var method2 = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });//输出数字 var dynamicMethod = typeBulder.DefineMethod("TryEx",MethodAttributes.Public,CallingConventions.Standard, typeof(string),new Type[] {typeof(object),typeof(object) });//构造方法 var il = dynamicMethod.GetILGenerator(); var local = il.DeclareLocal(typeof(string));//本地string类型变量 var ex = typeof(Exception); var localEx = il.DeclareLocal(ex);//本地Exception类型变量 var str = ex.GetMethod("ToString");//tostring方法 var exInstance = new Exception(); var localInt = il.DeclareLocal(typeof(int));//本地int变量 il.BeginExceptionBlock();//构造try块 il.Emit(OpCodes.Ldarg_1);//加载第一个变量 il.Emit(OpCodes.Unbox_Any,typeof(int));//加载第一个变量并且将obj转为int il.Emit(OpCodes.Ldarg_2);//加载第二个变量并且将obj转为int il.Emit(OpCodes.Unbox_Any, typeof(int));//加载第二个变量并且将obj转为int il.Emit(OpCodes.Add);//相加 il.Emit(OpCodes.Stloc,2);//赋值给本地第二个int变量 il.Emit(OpCodes.Ldloc, 2);//加载本地第二个int变量 il.Emit(OpCodes.Call, method2);//输出 il.Emit(OpCodes.Ldstr, "正常执行");//加载字符串 il.Emit(OpCodes.Stloc,0);//赋值给第0个变量 il.BeginCatchBlock(ex);//构造catch块 il.Emit(OpCodes.Stloc,1);//将ex赋值给本地exception变量 il.Emit(OpCodes.Ldloc,1); il.Emit(OpCodes.Callvirt, str);//加载本地ex变量并且tostring一下 il.Emit(OpCodes.Call, method);//输出异常信息 il.Emit(OpCodes.Ldstr, "非正常执行");//加载结果字符串 il.Emit(OpCodes.Stloc, 0);//赋值给第0个变量 il.Emit(OpCodes.Rethrow);//抛出异常 就是throw il.EndExceptionBlock();//结束catch块 il.Emit(OpCodes.Ldloc,0);//加载第0个字符串变量 il.Emit(OpCodes.Ret);//返回结果 var type = typeBulder.CreateType(); var instance = Activator.CreateInstance(type); var mh = type.GetMethod("TryEx"); var ttt= mh.Invoke(instance, new object[] { 10,new TestNewobj(1,1)});//此处可以修改为其他类型的变量,testnewobj是我测试用 } #endregion
好了,今天的分享就结束了,后续会持续更新,欢迎大家关注,