由於之前寫的表達式樹合集,未編寫任何注釋且是以圖片的形式展現給大家,在這里向各位看官道歉了,接下來為大家奉上新鮮出爐的香噴噴的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
好了,今天的分享就結束了,后續會持續更新,歡迎大家關注,