System.Reflection.Emit Learning

Source: Internet
Author: User
Tags emit reflector return tag type null

C # Reflection Emit System.Reflection.Emit LearningShare:1

I. Overview of SYSTEM.REFLECTION.EMIT

Emit, which can be called emit or produce. Classes related to emit are basically present under the System.Reflection.Emit namespace. Reflection, we can get a shape like what the assembly contains, what types contain the methods, and so on, and emit can generate code dynamically at run time.

Two, IL code parsing

The following code is an example:

1          static void Main (string[] args) 2          {3              int i = 1;4              int j = 2;5              int k = 3;6              Console.WriteLine (i+j+k) ; 7          }
View Code

The IL Code of the translated text is:

 1. Method private hidebysig static void Main (string[] args) cil managed 2 {3. entrypoint//Program entry 4//code Size (0x13) 5. Maxstack 3//defines the maximum depth of the stack used by the function code, or it can be understood as the number of variables of the call stack 6 7//The following we see it as the initialization in the completion code 8. Loca LS Init (int32 v_0,int32 v_1,int32 v_2)//define int type parameter v_0,v_1,v_2 (at this point v_0,v_1,v_2 has been deposited in call stack) 9 Il_0000:nop/ No Operation no action, we don't have to worry about it. il_0001:ldc.i4.1//load the first variable "I" (pressed into the evaluation stack) of Il_0002:stloc.   0//Assign the "I" to the No. 0 position in the call stack (V_0) il_0003:ldc.i4.2//load the second variable "J" (pressed into the evaluation stack) and il_0004: STLOC.1//Assign "J" to the 1th position in the call stack (v_1) il_0005:ldc.i4.3//Load Third variable "K" (pressed into evaluation stack) IL_0 006:STLOC.2//Assign "K" to the 2nd position in the call stack (v_2) 17 18//The above code initialization is done to start the output, the data from the call stack is removed from the IL_0007:LDL oc.0//takes the value of the element (V_0) at position 0 in the call stack (the value of "I") (equivalent to the value of V_0 in the call stack of copy one). The value of the v_0 itself is constant) IL_0008:LDLOC.1//Take the value of the element (V_1) at position 1 in the call stack ("J"(IBID.) Il_0009:add//Add operation IL_000A:LDLOC.2//Take out the value of the element (v_2) at position 2 in the call stack (value of "K") Il_ 000b:add//Do addition operation Il_000c:call Void [Mscorlib]system.console::writeline (Int32)//Call output method il_001 1:NOP27 Il_0012:ret//Returns the value of the return token.//end of method Program::main
View Code

Instruction detailed
Managed Heap: This is a dynamic Allocation memory that is automatically managed by Garbage Collector (GC) at execution time, and the entire Process is shared with a Managed heap (which I understand as the managed heap, Stores the value of the reference type).
Evaluation stack: This is a memory that is automatically managed by the. NET CLR at execution time, with each thread having its own Evaluation Stack (which I understand as a line stacks that temporarily holds the value type data)
Call stack: This is a memory that is automatically managed by the. NET CLR at execution time, and each Thread has its own call stack. Each call to a method will cause a record frame to be placed on the call Stack, and the record frame will be discarded (I understand it as a local variable table to hold the. Locals init (int32 v_0) directive parameter values such as: V_0)


. maxstack: Variables in the code need to occupy several positions in the call Stack
. Locals init (int32 v_0,int32 v_1,int32 v_2): Define variables and deposit in call stack
NOP: No Operation no action, we don't have to worry about it,
ldstr.: Load string to compress strings into the evaluation stack
stloc.: Assign values from the evaluation stack to the call stack
ldloc.: Remove the value of the specified position in the call stack (copy) into the Evaluation stack above two instructions for each other operation stloc assignment, ldloc value
Call: Invokes the specified method
RET: The return tag returns

Ii. Dynamic generation of code

First we need to understand what type of each dynamic type is represented in. Net.

Assembly: System.Reflection.Emit.AssemblyBuilder (defines and represents a dynamic assembly)

Constructor: System.Reflection.Emit.ConstructorBuilder (defines and represents a constructor for a dynamic class)

Custom properties: System.Reflection.Emit.CustomAttributeBuilder (Help build custom properties using parameters passed by the constructor to generate the properties of the Class)

Enumeration: System.Reflection.Emit.EnumBuilder (description and representation of enum type)

Event: System.Reflection.Emit.EventBuilder (defines event for class)

Field: System.Reflection.Emit.FieldBuilder (defines and represents a field.) Cannot inherit this class)

Local variable: System.Reflection.Emit.LocalBuilder (represents a local variable within a method or constructor)

Method: System.Reflection.Emit.MethodBuilder (defines and represents a method (or constructor) for a dynamic Class)

Module: System.Reflection.Emit.ModuleBuilder (defines and represents a module in a dynamic assembly)

Parameters: System.Reflection.Emit.ParameterBuilder (Create or correlate parameter information such as: Method parameters, event arguments, etc.)

Properties: System.Reflection.Emit.PropertyBuilder (property) of the defined type

Class: System.Reflection.Emit.TypeBuilder (defines and creates a new instance of the class at run time)

The following describes the basic process of generating code for emit:

1. Building Assemblies

Before we create the assembly, we need to name it first.

var asmname = new AssemblyName ("Test");

AssemblyName is located under the System.Reflection namespace, which represents the name of the assembly.

Then we can use the name above to create an assembly:

var asmbuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (Asmname, Assemblybuilderaccess.runandsave);

Assemblybuilderaccess.reflectiononly:
DefineDynamicAssembly has a lot of overloads, such as the example above, you can add a third parameter to the directory where the generated assembly will be stored. For other overloaded forms, you can check out MSDN. Here is the key to assemblybuilderaccess this enumeration.
It has the following values:
Assemblybuilderaccess.reflectiononly: Indicates that the dynamic assembly can only be used for reflection fetching elements and cannot be executed.
Assemblybuilderaccess.run: Indicates that the dynamic assembly is for execution.
Assemblybuilderaccess.save: Indicates that the dynamic assembly is saved to disk and cannot be executed immediately.
Assemblybuilderaccess.runandsave: Indicates that the dynamic assembly is saved to disk and can be executed immediately.

2. Create a module

Once the assembly is created, you need to add modules to the assembly, and we can define a module as follows:

var mdlbldr = asmbuilder.definedynamicmodule ("Main", "Main.dll");

If you want to save the dynamically generated assembly to disk (as in this example), the file name of the module when you define the module must be the same as the file name that is provided when you save the assembly (which is mentioned later).

3. Defining classes

With the preparatory work ahead, we begin to define our type:

var typebldr = Mdlbldr.definetype ("Hello", typeattributes.public);

DefineType can also set the base class for the class to be defined, the interface to implement, and so on.

4. Define class members (methods, properties, and so on)

Now that you have the class, let's add a SayHello method to it:

1 var methodbldr = Typebldr.definemethod (2     "SayHello",     3      methodattributes.public,                 4      null,// return type                5      null//parameter type                6);

The prototype of this method is public void Sayhell ();

The method signature has been generated, but the method is missing the implementation. Before generating the implementation of a method, one important concept must be mentioned: evaluation stack. Basically all of the operations under. NET are done through the stack-out stack. This stack is the evaluation stack. For example, to calculate the sum of two (a, b), first put a into the evaluation stack, and then the B is also put into the stack, the last addition will pop up the top of the two elements of the stack is a and B, add and then push the results to the top of the stack.

Console.WriteLine ("Hello,world") can be generated with emit:

1 var il = methodbldr.getilgenerator ();//Get IL generator 2 3 il. Emit (Opcodes.ldstr, "Hello, World"); 4 5 IL. Emit (Opcodes.call,typeof (Console). GetMethod ("WriteLine", New Type[]{typeof (String)})); 6 7 IL. Emit (Opcodes.ret);

The Opcodes enumeration defines all possible operations, which are used here:

LDSTR: Loads a string into the evaluation stack.

Call: Invokes a method.

Ret: Returns the top value of the stack when the evaluation stack has a value.

To complete the above steps, a type seems to have been completed. In fact, not yet, finally we must also display the call CreateType to complete the creation of the type.

Typebldr.createtype ();

Such a complete class is done. But to be able to view the dynamic assembly we created with reflector, we chose to save the assembly.

Asmbuilder.save ("Main.dll");

As mentioned in the previous definition of the module, the file name must be the same as the module saved to the file, otherwise we define the module and this module everything is homeless. Next, (If you do not specify which directory the dynamically created program will be saved to when you define the module) we can go to the debug directory to see the generated Main.dll, open with reflector to see:


Third, the console program that does not contain main

All along, the application (console, WinForm) was started from the main function, and if no main can be started? The answer is yes, the following is the use of emit to do such a console program, the complete code is as follows:

 1 var asmname = new AssemblyName ("Test");                 2 3 var asmbuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (4 5 asmname, 6 7   Assemblybuilderaccess.runandsave);  8 9 var mdlbldr = Asmbuilder.definedynamicmodule ("Main", "Main.exe");  Ten-one var typebldr = Mdlbldr.definetype ("Hello", typeattributes.public); var methodbldr = Typebldr.definemethod ("SayHello", + M Ethodattributes.public | Methodattributes.static, Null,//return type Null//parameter            Type 22 23); The var il = methodbldr.getilgenerator ();//Gets the Il generator, il.    Emit (Opcodes.ldstr, "Hello, World"); (IL). Emit (Opcodes.call, typeof (Console). GetMethod ("WriteLine", New Type[]{typeof (String)})); To IL. Emit (Opcodes.call, typeof (Console). GetmethOD ("ReadLine")); The IL. Emit (Opcodes.pop);//The value read in is pushed to the evaluation stack, and this method has no return value, so the value on the stack needs to be discarded.                     Emit (Opcodes.ret);          N-notoginseng var t = typebldr.createtype ();    Asmbuilder.setentrypoint (T.getmethod ("SayHello")); Asmbuilder.save ("Main.exe");

System.Reflection.Emit Learning

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.