IL preliminary understanding, preliminary understanding of English
I. Overview:
Recently, I have been looking at AOP and learned that Emit can be implemented. Previous knowledge of Emit is part of the commands decompiled by Reflector. I will use this opportunity to learn the learning process of Emit. I also hope you can give me some guidance in some areas I don't know.
You can learn about Opcodes before learning.
Ii. Tools
1. vs2015
2.. NET Reflector 9.0
Iii. Example
1. Output Hello World
C # code
static void Main(string[] args) { Console.WriteLine("Hello world!"); }
View Code
Decompile the obtained IL code
Emit implementation code
Public void HellowWorld () {// defines the Hellow method. No return value. No parameter. DynamicMethod helloWorldMethod = new DynamicMethod ("HellowWorld", null, null). // creates an IL, dynamically generated code ILGenerator IL = helloWorldMethod. getILGenerator (); // pushes the output to the stack IL. emit (OpCodes. ldstr, "Hello World! "); // Execute Console. writeLine IL. emit (OpCodes. call, typeof (Console ). getMethod ("WriteLine", new Type [] {typeof (string)}); // The method ends IL. emit (OpCodes. ret); HelloWordDelegate Method = (HelloWordDelegate) helloWorldMethod. createDelegate (typeof (HelloWordDelegate); Method ();}
View Code
The request is being called. If a parameter exists, the system prompts "the operation may damage the runtime stability ". (Not clear)
4. Build an assembly
1. The following describes how to create an instance by constructing a class that contains two methods.
public int Add(int a, int b) { return a + b; } public string AddList(string[] array) { string result = string.Empty; for (int i = 0; i < array.Length; i++) { result = result + array[i]; } return result; }
View Code
2. Check the IL code decompiled by the two methods.
Next, let's take a look at how IL is implemented.
● L0000 to L0009: Assign string. Empty to the custom variable resultName, load the integer 0, L0009 to jump to L001b for execution
● L001b to L0027: load 1 index value, load parameter 1 (Static starting from 0), Ldlen pushes the number of arrays from 0 to the stack, and compares the size of the two values, (store the comparison result at index 2, and then retrieve it (this step can be omitted), and then jump to L_000b for execution.
● L000b to L001a: load the index value at 0, and load parameter 1. Ldelem_Ref is used to load string-type Elements and execute string. the concat method stores the value at index 0, loads the value at Index 1, loads the integer 1, adds the two values, and stores the value at index 0.
● L002a end return
3. The following is implemented through Emit code:
Public void GenerateAssembly () {string name = "IL. dynamic "; string fileName = string. format ("{0 }. dll ", name); // build Assembly AssemblyName assemblyName = new AssemblyName (name); // application Assembly domain AppDomain domain = AppDomain. currentDomain; // instantiate an AssemblyBuilder object to construct a dynamic assembly AssemblyBuilder assemblyBuilder = domain. defineDynamicAssembly (assemblyName, AssemblyBuilderAccess. runAndSave); // defines the module (without filename being a transient module, not persistent) ModuleBuilder moduleBuilder = assemblyBuilder. defineDynamicModule (name); // define the type TypeBuilder typeBuilder = moduleBuilder. defineType (name, TypeAttributes. public); // define an Add method to simply Add MethodBuilder methodBuilder = typeBuilder. defineMethod ("Add", MethodAttributes. public, typeof (Int32), new Type [] {typeof (int), typeof (int)}); // IL implements ILGenerator IL = methodBuilder. getILGenerator (); IL. emit (OpCodes. ldarg_1); IL. emit (OpCodes. ldarg_2); IL. emit (OpCodes. add); IL. emit (OpCodes. ret); // defines an AddList string using the for concatenation method MethodBuilder method2Builder = typeBuilder. defineMethod ("AddList", MethodAttributes. public | MethodAttributes. static, typeof (string), new Type [] {typeof (string [])}); FieldBuilder fieldName = typeBuilder. defineField ("resultName", typeof (string), FieldAttributes. private | FieldAttributes. static); ILGenerator addIL = method2Builder. getILGenerator (); // local variable used to save the sum result LocalBuilder resultStr = addIL. declareLocal (typeof (String); // The local variable LocalBuilder I = addIL used in the loop. declareLocal (typeof (Int32); Label concatLabel = addIL. defineLabel (); Label LoopLabel = addIL. defineLabel (); // set string result = string. empty; addIL. emit (OpCodes. ldsfld, fieldName); addIL. emit (OpCodes. stloc_0); // set I = 0 addIL. emit (OpCodes. ldc_I4_0); addIL. emit (OpCodes. stloc_1); addIL. emit (OpCodes. br, concatLabel); // enter the loop body addIL. markLabel (LoopLabel); addIL. emit (OpCodes. ldloc_0); // The parameter specifies that the static state starts from 0 addIL. emit (OpCodes. ldarg_0); addIL. emit (OpCodes. ldloc_1); // Ldelem_Ref is used to load the string type element addIL. emit (OpCodes. ldelem_Ref); addIL. emit (OpCodes. call, typeof (string ). getMethod ("Concat", new Type [] {typeof (string), typeof (string)}); addIL. emit (OpCodes. stloc_0); addIL. emit (OpCodes. ldloc_1); // I ++ addIL. emit (OpCodes. ldc_I4_1); addIL. emit (OpCodes. add); addIL. emit (OpCodes. stloc_1); addIL. markLabel (concatLabel); addIL. emit (OpCodes. ldloc_1); addIL. emit (OpCodes. ldarg_0); addIL. emit (OpCodes. ldlen); addIL. emit (OpCodes. conv_I4); // Clt compare the two values of addIL. emit (OpCodes. clt); addIL. emit (OpCodes. brtrue_S, LoopLabel); addIL. emit (OpCodes. ldloc_0); addIL. emit (OpCodes. ret); Type type = typeBuilder. createType (); assemblyBuilder. save (fileName); int [] ints = new int [] {1, 2, 3, 4}; string [] array = new string [] {"", "B", "c"}; object ob = Activator. createInstance (type); var result = type. getMethod ("Add "). invoke (ob, new object [] {8, 9}); var result1 = type. getMethod ("AddList "). invoke (ob, new object [] {array });}
View Code
3.1 AssemblyBuilderAccess
Run |
It can be executed but cannot be saved |
Save |
Save but cannot execute |
RunAndSave |
Can be executed and saved |
ReflectionOnly |
Load only in reflection Context |
4. Running output
4.1 generate a file
View the C # code generated by IL by decompiling with tools
4.2 running results
Through this example, we can have a basic understanding of IL, and continue to talk with you later. Download System. IL from the project