Emit Learning (3), emit Learning
I was going to directly access Dapper, but I checked a lot of content yesterday. Dapper is a mature framework. It is very practical to consider various situations, however, this makes it impossible for me to finish reading it in a short time, so I have to wait for a few days.
Let's take a look at the loop and exceptions. When we look at the IL jump, there is a tag that jumps and jumps. In OpCodes, there is a corresponding implementation.
I. Example
public static void Xunhuan(int num) { try { int sum = 0; if (num < 1) { throw new Exception("num is less than 1"); } for (int i = 1; i <= num; i++) { sum += i; } Console.WriteLine("executed successfully : Sum = " + sum); } catch (Exception e) { Console.WriteLine("error happened : " + e.Message); } }
When calling Xunhuan (), when a value smaller than 1 is passed in, an exception is thrown to go to The Exception Handling Section. Otherwise, the exception enters the loop (here for demonstration, a loop is used, otherwise, use the algorithm to calculate the result), Sum. as a result, I will not post it.
Ii. OpCodes implementation
Static Action <int> action; static void Main (string [] args) {// defines a dynamic method var method = new DynamicMethod ("Xunhuan", null, new Type [] {typeof (int)}); ILGenerator IL = method. getILGenerator (); // defines the label var label1 = IL. defineLabel (); var xunLabel = IL. defineLabel (); var endLabel = IL. defineLabel (); // defines the local variable var sum = IL. declareLocal (typeof (int); var I = IL. declareLocal (typeof (int); IL. emit (OpCodes. ldc_I4_0); IL. emit (OpCodes. stloc_0); // sum = 0 IL. emit (OpCodes. ldc_I4_1); IL. emit (OpCodes. stloc_1); // I = 1 IL. emit (OpCodes. ldstr, "enter number: num ="); IL. emit (OpCodes. ldarg_0); // the implementation method is to pack IL. emit (OpCodes. box, typeof (int); // boxed IL. emit (OpCodes. call, typeof (string ). getMethod ("Concat", new Type [] {typeof (string), typeof (object)}); IL. emit (OpCodes. call, typeof (Console ). getMethod ("WriteLine", new Type [] {typeof (string)}); Label tryLabel = IL. beginExceptionBlock (); // try IL. emit (OpCodes. ldarg_0); // num IL. emit (OpCodes. ldc_I4_1); // 1 IL. emit (OpCodes. bge, label1); // num> = 1-> label1, note: the jump in the try cannot jump out of the try statement, but can only be in the internal IL. emit (OpCodes. ldstr, "num is less than 1"); IL. emit (OpCodes. newobj, typeof (Exception ). getConstructor (new Type [] {typeof (string)}); // new Exception (); IL. emit (OpCodes. throw); // throw IL. markLabel (label1); IL. emit (OpCodes. ldloc_1); // I IL. emit (OpCodes. ldarg_0); // num IL. emit (OpCodes. bgt, xunLabel); // I> num-> endLabel IL. emit (OpCodes. ldloc_0); IL. emit (OpCodes. ldloc_1); IL. emit (OpCodes. add); IL. emit (OpCodes. stloc_0); // sum + = I; IL. emit (OpCodes. ldloc_1); IL. emit (OpCodes. ldc_I4_1); IL. emit (OpCodes. add); IL. emit (OpCodes. stloc_1); // I + = 1; IL. emit (OpCodes. br_S, label1); IL. markLabel (xunLabel); IL. emit (OpCodes. ldstr, "executed successfully: Sum ="); IL. emit (OpCodes. ldloc_0); // method 2 call Convert. toString (int num) method IL. emit (OpCodes. call, typeof (Convert ). getMethod ("ToString", new Type [] {typeof (int)}); IL. emit (OpCodes. call, typeof (string ). getMethod ("Concat", new Type [] {typeof (string), typeof (string)}); IL. emit (OpCodes. call, typeof (Console ). getMethod ("WriteLine", new Type [] {typeof (object)}); IL. markLabel (endLabel); IL. emit (OpCodes. nop); IL. beginCatchBlock (typeof (Exception); // catch IL. emit (OpCodes. callvirt, typeof (Exception ). getMethod ("get_Message"); IL. emit (OpCodes. call, typeof (Console ). getMethod ("WriteLine", new Type [] {typeof (string)}); IL. endExceptionBlock (); // end IL. emit (OpCodes. ret); action = (Action <int>) method. createDelegate (typeof (Action <int>); // call the method by Delegate, instead of saving it as a dll file on the Console. writeLine ("------------- normal execution ---------------"); action. invoke (10); Console. writeLine ("------------- abnormal execution -------------"); action. invoke (-10); Console. readKey ();}
The implementation method is not the only one. The method I wrote is not the simplest. Below I will post the reflector decompiled IL code, which is quite different from what I wrote.
.method public hidebysig static void Xunhuan(int32 num) cil managed { .maxstack 2 .locals init ( [0] int32 num2, [1] int32 num3, [2] class [mscorlib]System.Exception exception, [3] bool flag) L_0000: nop L_0001: nop L_0002: ldc.i4.0 L_0003: stloc.0 L_0004: ldarg.0 L_0005: ldc.i4.1 L_0006: clt L_0008: ldc.i4.0 L_0009: ceq L_000b: stloc.3 L_000c: ldloc.3 L_000d: brtrue.s L_001b L_000f: nop L_0010: ldstr "num is less than 1" L_0015: newobj instance void [mscorlib]System.Exception::.ctor(string) L_001a: throw L_001b: ldc.i4.1 L_001c: stloc.1 L_001d: br.s L_0029 L_001f: nop L_0020: ldloc.0 L_0021: ldloc.1 L_0022: add L_0023: stloc.0 L_0024: nop L_0025: ldloc.1 L_0026: ldc.i4.1 L_0027: add L_0028: stloc.1 L_0029: ldloc.1 L_002a: ldarg.0 L_002b: cgt L_002d: ldc.i4.0 L_002e: ceq L_0030: stloc.3 L_0031: ldloc.3 L_0032: brtrue.s L_001f L_0034: ldstr "executed successfully : Sum = " L_0039: ldloc.0 L_003a: box int32 L_003f: call string [mscorlib]System.String::Concat(object, object) L_0044: call void [mscorlib]System.Console::WriteLine(string) L_0049: nop L_004a: nop L_004b: leave.s L_0068 L_004d: stloc.2 L_004e: nop L_004f: ldstr "error happened : " L_0054: ldloc.2 L_0055: callvirt instance string [mscorlib]System.Exception::get_Message() L_005a: call string [mscorlib]System.String::Concat(string, string) L_005f: call void [mscorlib]System.Console::WriteLine(string) L_0064: nop L_0065: nop L_0066: leave.s L_0068 L_0068: nop L_0069: ret .try L_0001 to L_004d catch [mscorlib]System.Exception handler L_004d to L_0068 }
In the past, I was always lazy. I had to look at and understand new knowledge. But in the actual writing process, I encountered a lot of problems that I would not encounter, the code can be written without looking at it. It is better to have a good memory than a bad pen. You have to repeat the code row by row to find the problem.