Emit Learning (3), emit Learning

Source: Internet
Author: User
Tags emit

Emit Learning (3), emit Learning

The last article introduced the part of IL, the basic part, which will be introduced here for the time being. The next step is to enter the code compiling stage.

Today's topic is to dynamically create classes, attributes, and methods during code execution.

Source: http://www.cnblogs.com/yingql/archive/2009/03/22/1419149.html

No more nonsense. Let's look at the example above.

I. Example

The examples used here are the same as those in the source. Please refer to the Code:

public class Add    {        int numA = 0;        public int NumA  {  get { return numA; }  set { numA = value; }  }        int numB = 0;        public int NumB  { get { return NumB; } set { NumB = value; } }        public Add(int a, int b)        {            numA = a;            numB = b;        }        public int Calc()        {            return numA + numB;        }    }

We want to dynamically create such a class. We will not show you the encoding process first. Let's show you the results first. What can we get by doing this first.

After running the code, an Elvin. dll file will be obtained in the bin, and the file and ConsoleApplication2.exe will be decompiled together to see the content of the Add class in it.

By comparison, the native and dynamic generation are slightly different, And the IL code in it is also partially different. This is normal. Although it is written based on the decompiled code, it is only a reference, not exactly the same.

 

Ii. Encoding

Let's take a look at several major parts. I will post the complete code later.

1. Fields

Private int numA; -->. field private int32 numA
Var fieldABuilder = typeBldr. DefineField ("numA", typeof (Int32), FieldAttributes. Private); // fieldABuilder. SetConstant (0); this is the sub-initial value, which can be omitted here

I can understand it at a Glance. For the moment, this typeBldr does not care about it.

2. Attributes

// 1. attribute public int NumA {get {return numA;} set {numA = value ;}} var propertyABuilder = typeBldr. defineProperty ("NumA", PropertyAttributes. none, CallingConventions. hasThis, typeof (Int32), null); // 2. define the get and set methods
// 2.1 The Code Part Of The get method is somewhat different from the preceding one. The parameter var getPropertyABuilder = typeBldr is based on this parameter. defineMethod ("get", MethodAttributes. public | MethodAttributes. specialName | MethodAttributes. hideBySig, typeof (Int32), Type. emptyTypes); // ILGenerator var getAIL = getPropertyABuilder. getILGenerator (); getAIL. emit (OpCodes. ldarg_0); // this getAIL. emit (OpCodes. ldfld, fieldABuilder); // numA getAIL. emit (OpCodes. ret); // return numA

// 2.2 The Code part of the set method is different from that of the medium method. It is the var setPropertyABuilder = typeBldr parameter. defineMethod ("set", MethodAttributes. public | MethodAttributes. specialName | MethodAttributes. hideBySig, typeof (void), new Type [] {typeof (Int32)}); // ILGenerator var setAIL = setPropertyABuilder. getILGenerator (); // setAIL. emit (OpCodes. nop); // This sentence can omit setAIL. emit (OpCodes. ldarg_0); // this setAIL. emit (OpCodes. ldarg_1); // value setAIL. emit (OpCodes. stfld, fieldABuilder); // numA = value; setAIL. emit (OpCodes. ret); // return; // 3. bind the get and set methods to the properties propertyABuilder. setGetMethod (getPropertyABuilder); propertyABuilder. setSetMethod (setPropertyABuilder );

In many cases, we use anonymous attributes, such as public int NumA {get; set;}. In this case, an anonymous private variable is automatically generated to replace numA, to match with it, attributes are essentially methods and cannot be used to store data.

3. Constructor

IL code:
. Method public hidebysig specialname rtspecialname instance void. ctor (int32 a, int32 B) CER managed {. maxstack 8 L_0000: ldarg.0 L_0001: ldc. i4.0 L_0002: st1_int32 ConsoleApplication2.Add: numA L_0007: ldarg.0 L_0008: ldc. i4.0 L_0009: st1_int32 ConsoleApplication2.Add: numB L_000e: ldarg.0 L_000f: call instance void [mscorlib] System. object ::. ctor () L_0014: nop L_0015: nop L_0016: ldarg.0 L_0017: ldarg.1 L_0018: st1_int32 failed: numA L_001d: ldarg.0 L_001e: ldarg.2 failed: st1_int32 failed: numB L_0024: nop L_0025: ret} // defines the ConstructorBuilder var constructorBuilder = typeBldr. defineConstructor (MethodAttributes. public | MethodAttributes. hideBySig, CallingConventions. hasThis, new Type [] {typeof (Int32), typeof (Int32)}); var ctorIL = constructorBuilder. getILGenerator (); // numA = a; ctorIL. emit (OpCodes. ldarg_0); ctorIL. emit (OpCodes. ldarg_1); ctorIL. emit (OpCodes. stfld, fieldABuilder); // NumB = B; ctorIL. emit (OpCodes. ldarg_0); ctorIL. emit (OpCodes. ldarg_2); ctorIL. emit (OpCodes. stfld, fieldBBuilder); ctorIL. emit (OpCodes. ret );

4. Method

IL code:
. Method public hidebysig instance int32 Calc () cel managed {. maxstack 2. locals init ([0] int32 num) L_0000: nop L_0001: ldarg.0 L_0002: ld1_int32 failed: numA L_0007: ldarg.0 L_0008: ld1_int32 ConsoleApplication2.Add: numB L_000d: add L_000e: stloc.0 L_000f: br. s L_0011 L_0011: ldloc.0 L_0012: ret} // 8. definition method: MethodBuilder var calcMethodBuilder = typeBldr. defineMethod ("Calc", MethodAttributes. public | MethodAttributes. hideBySig, typeof (Int32), Type. emptyTypes); var calcer = calcMethodBuilder. getILGenerator (); // load the private field numA calcer. emit (OpCodes. ldarg_0); calcel. emit (OpCodes. ldfld, fieldABuilder); // loads the NumB calcer attribute. emit (OpCodes. ldarg_0); calcel. emit (OpCodes. ldfld, fieldBBuilder); // you want to add and return the value of the top of the stack, calcel. emit (OpCodes. add); calcel. emit (OpCodes. ret );

5. At this point, the main part is described, and the following part of the test is provided:

// 9. result Type type = typeBldr. createType (); int a = 2; int B = 3; Object ob = Activator. createInstance (type, new object [] {a, B}); Console. writeLine ("The Result of {0} + {1} is {2}", type. getProperty ("NumA "). getValue (ob), type. getProperty ("NumB "). getValue (ob), ob. getType (). getMethod ("Calc "). invoke (ob, null ));

After The command is executed, The Result of 2 + 3 is 5 is output"

So far, the part to be introduced today is over. I will post my learning process and results for interested children's shoes to take a look.

The complete code is as follows:

Static void Main (string [] args) {// 1. build the Assembly var asmName = new AssemblyName ("Elvinle"); var asmBuilder = AppDomain. currentDomain. defineDynamicAssembly (asmName, AssemblyBuilderAccess. runAndSave); // 2. create module var mdlBldr = asmBuilder. defineDynamicModule ("Elvin", "Elvin. dll "); // 3. definition class, public class Add var typeBldr = mdlBldr. defineType ("Add", TypeAttributes. public | TypeAttributes. beforeFieldInit); // 4. define attributes and fields // 4.1 Field FieldBuilder var fieldABuilder = typeBldr. defineField ("numA", typeof (Int32), FieldAttributes. private); // fieldABuilder. setConstant (0); this is the sub-Initial Value. var fieldBBuilder = typeBldr can be omitted here. defineField ("numB", typeof (Int32), FieldAttributes. private); // 4.2 property PropertyBuilder var propertyABuilder = typeBldr. defineProperty ("NumA", PropertyAttributes. none, CallingConventions. hasThis, typeof (Int32), null); var propertyBBuilder = typeBldr. defineProperty ("NumB", PropertyAttributes. none, CallingConventions. hasThis, typeof (Int32), null); // 5. define the get; set; Method MethodBuilder for the property numA // 5.1 get method var getPropertyABuilder = typeBldr. defineMethod ("get", MethodAttributes. public | MethodAttributes. specialName | MethodAttributes. hideBySig, typeof (Int32), Type. emptyTypes); // ILGenerator GetPropertyIL (getPropertyABuilder, fieldABuilder); // var getAIL = getPropertyABuilder. getILGenerator (); // getAIL. emit (OpCodes. ldarg_0); // this // getAIL. emit (OpCodes. ldfld, fieldABuilder); // numA // getAIL. emit (OpCodes. ret); // return numA // 5.2 set method var setPropertyABuilder = typeBldr. defineMethod ("set", MethodAttributes. public | MethodAttributes. specialName | MethodAttributes. hideBySig, typeof (void), new Type [] {typeof (Int32)}); // ILGenerator SetPropertyIL (setPropertyABuilder, fieldABuilder); // var setAIL = setPropertyABuilder. getILGenerator (); // setAIL. emit (OpCodes. nop); // This sentence can be omitted // setAIL. emit (OpCodes. ldarg_0); // this // setAIL. emit (OpCodes. ldarg_1); // value // setAIL. emit (OpCodes. stfld, fieldABuilder); // numA = value; // setAIL. emit (OpCodes. ret); // return; // 5.3 bind propertyABuilder. setGetMethod (getPropertyABuilder); propertyABuilder. setSetMethod (setPropertyABuilder); // 6. define the get; set; method of the numA property; MethodBuilder var getPropertyBBuilder = typeBldr. defineMethod ("get", MethodAttributes. public | MethodAttributes. specialName | MethodAttributes. hideBySig, typeof (Int32), Type. emptyTypes); GetPropertyIL (getPropertyBBuilder, fieldBBuilder); var setPropertyBBuilder = typeBldr. defineMethod ("set", MethodAttributes. public | MethodAttributes. specialName | MethodAttributes. hideBySig, typeof (void), new Type [] {typeof (Int32)}); SetPropertyIL (setPropertyBBuilder, fieldBBuilder); propertyBBuilder. setGetMethod (getPropertyBBuilder); propertyBBuilder. setSetMethod (setPropertyBBuilder); // 7. define ConstructorBuilder var constructorBuilder = typeBldr. defineConstructor (MethodAttributes. public | MethodAttributes. hideBySig, CallingConventions. hasThis, new Type [] {typeof (Int32), typeof (Int32)}); var ctorIL = constructorBuilder. getILGenerator (); // numA = a; ctorIL. emit (OpCodes. ldarg_0); ctorIL. emit (OpCodes. ldarg_1); ctorIL. emit (OpCodes. stfld, fieldABuilder); // NumB = B; ctorIL. emit (OpCodes. ldarg_0); ctorIL. emit (OpCodes. ldarg_2); ctorIL. emit (OpCodes. stfld, fieldBBuilder); ctorIL. emit (OpCodes. ret); // 8. definition method: MethodBuilder var calcMethodBuilder = typeBldr. defineMethod ("Calc", MethodAttributes. public | MethodAttributes. hideBySig, typeof (Int32), Type. emptyTypes); var calcer = calcMethodBuilder. getILGenerator (); // load the private field numA calcer. emit (OpCodes. ldarg_0); calcel. emit (OpCodes. ldfld, fieldABuilder); // loads the NumB calcer attribute. emit (OpCodes. ldarg_0); calcel. emit (OpCodes. ldfld, fieldBBuilder); // sum and return the value of calcel at the top of the stack. emit (OpCodes. add); calcel. emit (OpCodes. ret); // 9. result Type type = typeBldr. createType (); int a = 2; int B = 3; Object ob = Activator. createInstance (type, new object [] {a, B}); Console. writeLine ("The Result of {0} + {1} is {2}", type. getProperty ("NumA "). getValue (ob), type. getProperty ("NumB "). getValue (ob), ob. getType (). getMethod ("Calc "). invoke (ob, null); asmBuilder. save ("Elvin. dll "); Console. readKey ();} private static void GetPropertyIL (MethodBuilder getPropertyBuilder, FieldBuilder fieldBuilder) {// ILGenerator var getAIL = getPropertyBuilder. getILGenerator (); getAIL. emit (OpCodes. ldarg_0); // this getAIL. emit (OpCodes. ldfld, fieldBuilder); // numA getAIL. emit (OpCodes. ret); // return numA} private static void SetPropertyIL (MethodBuilder setPropertyBuilder, FieldBuilder fieldBuilder) {// ILGenerator var setAIL = setPropertyBuilder. getILGenerator (); // setAIL. emit (OpCodes. nop); // This sentence can omit setAIL. emit (OpCodes. ldarg_0); // this setAIL. emit (OpCodes. ldarg_1); // value setAIL. emit (OpCodes. stfld, fieldBuilder); // numA = value; setAIL. emit (OpCodes. ret); // return ;}
View Code

I hope I can bring you some different things in the course of learning!

 

Related Article

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.