IL interface and class attributes, IL interface attributes
In the previous article, I learned how to get started with IL. Next, I will use two examples to understand the attributes, constructor, and Interface Usage of the class.
I. class attributes and constructors
1. first take a look at the C # code of the class we want to build and then implement IL. The sample code is as follows:
[Serializable] public class Dynamic {public int _ a = 0; public const string ConstField = "const "; /// <summary> /// define attributes /// </summary> public int A {get; set ;} /// <summary> /// constructor /// </summary> /// <param name = "num"> </param> public Dynamic (int num) {this. A = num;} public int Add (int num) {return this. A + num ;}}
View Code
2. With the above code, we can first define field _ a and constant ConstField as required (not used during the constructor process to help the Group understand the creation of class attributes) and add serialization labels to the class, the property can be created through DefineField of TypeBuilder, And the serialization tag needs to be created through typemattributebuilder of TypeBuilder. The sample code is as follows:
// The definition class can be serialized CustomAttributeBuilder serializable = new CustomAttributeBuilder (typeof (SerializableAttribute ). getConstructor (Type. emptyTypes), new Type [] {}); typeBuilder. setCustomAttribute (serializable); // defines the constant FieldBuilder fieldConst = typeBuilder. defineField ("ConstField", typeof (string), FieldAttributes. static | FieldAttributes. public | FieldAttributes. literal); fieldConst. setConstant ("const"); // defines the field _ a FieldBuilder aField = typeBuilder. defineField ("_ a", typeof (int), FieldAttributes. private); aField. setConstant (0 );
View Code
3. Define property A through DefineProperty of TypeBuilder and add corresponding labels to the property through CustomAttributeBuilder. The sample code is as follows:
// Define the property A PropertyBuilder propertyABuilder = typeBuilder. defineProperty ("A", PropertyAttributes. none, typeof (int), null); CustomAttributeBuilder desAttributeBuilder = new CustomAttributeBuilder (typeof (DescriptionAttribute ). getConstructor (new Type [] {typeof (string)}), new object [] {"attribute A"}); propertyABuilder. setCustomAttribute (desAttributeBuilder); // field description
View Code
4. Define the get method and set Method of the attribute. The get and set methods are the same as normal methods, and are created using DefineMethod of TypeBuilder. The sample code is as follows:
// Define the property get method MethodBuilder methodABuilder = typeBuilder. defineMethod ("get", MethodAttributes. public, typeof (Int32), Type. emptyTypes); ILGenerator GetIL = methodABuilder. getILGenerator (); GetIL. emit (OpCodes. ldarg_0); GetIL. emit (OpCodes. ldtil, aField); GetIL. emit (OpCodes. ret); propertyABuilder. setGetMethod (methodABuilder); // defines the property set method MethodBuilder methodBBuilder = typeBuilder. defineMethod ("set", MethodAttributes. public, typeof (Int32), new Type [] {typeof (Int32)}); ILGenerator SetIL = methodBBuilder. getILGenerator (); SetIL. emit (OpCodes. ldarg_0); SetIL. emit (OpCodes. ldarg_1); SetIL. emit (OpCodes. sttil, aField); SetIL. emit (OpCodes. ret); propertyABuilder. setSetMethod (methodBBuilder );
View Code
5. Create a constructor. The constructor is obtained through DefineConstructor of TypeBuilder. The constructor contains a parameter and is assigned to _ a. The sample code is as follows:
// Define the ConstructorBuilder constructorBuilder = typeBuilder. defineConstructor (MethodAttributes. public, CallingConventions. hasThis, new Type [] {typeof (Int32)}); ILGenerator constructorIL = constructorBuilder. getILGenerator (); constructorIL. emit (OpCodes. ldarg_0); constructorIL. emit (OpCodes. ldarg_1); constructorIL. emit (OpCodes. stfield, aField); constructorIL. emit (OpCodes. ret );
View Code
6. Define the method.
// Define method MethodBuilder methodAddBuild = typeBuilder. defineMethod ("Add", MethodAttributes. public, typeof (Int32), new Type [] {typeof (int)}); ILGenerator addIL = methodAddBuild. getILGenerator (); addIL. emit (OpCodes. ldarg_0); addIL. emit (OpCodes. ld1_, aField); addIL. emit (OpCodes. ldarg_1); addIL. emit (OpCodes. add); addIL. emit (OpCodes. ret );
View Code
In this step, the attributes, constructors, and methods of a dynamic class are created. You can use reflector to view the generated results. As follows:
Public int A {get; set;} to public int A5 {get {return _ a;} set {_ a = value ;}}
It is easier to understand the existence of _
Ii. Interface implementation
1. First, let's look at what kind of interface we want to implement. First, let's look at the C # code of the build class. The sample code is as follows:
public class Mail : IMail { public string SendMail() { return "Send Success"; } } public interface IMail { string SendMail(); }
View Code
2. Implement the interface. We use IMail directly. You don't need to use IL to create it. First, we create a typeBuilder and specify the inheritance interface IMail. You can use AddInterfaceImplementation to perform operations. The sample code is as follows:
// Define the type TypeBuilder typeBuilder = moduleBuilder. DefineType (name, TypeAttributes. Public); typeBuilder. AddInterfaceImplementation (typeof (IMail ));
View Code
3. Implementation interface. You can use reflector to decompile a method to implement the interface without knowing how to define the interface implementation method. Observe the MethodAttributes attributes required by the method.
You can use the above information to define the methods implemented by the interface. The implementation of the interface is the same as that defined in the previous example. The sample code is as follows:
MethodBuilder sendMailBuilder = typeBuilder. defineMethod ("SendMail", MethodAttributes. public | MethodAttributes. reuseSlot | MethodAttributes. virtual | MethodAttributes. hideBySig, typeof (string), null); // defines the interface ILGenerator mailIL = sendMailBuilder. getILGenerator (); LocalBuilder resultStr = mailIL. declareLocal (typeof (String); mailIL. emit (OpCodes. nop); mailIL. emit (OpCodes. ldstr, "Send Success1"); mailIL. emit (OpCodes. stloc_0); mailIL. emit (OpCodes. ldloc_0); mailIL. emit (OpCodes. ret );
View Code
After implementation, check the Code through IL as follows:
Through decompilation, it is found that the interface is implemented with the override keyword. If the virtual attribute is not included in the implementation method definition, the interface is not implemented. Please also know your friends to solve my doubts.
Through this article, we learned how to create dynamic classes and how to use interfaces. From these two examples, we can expand a lot of things, such as inheritance, property binding custom tags, and virtual method rewriting ...... these things also need to be learned constantly. There are still a lot of learning in IL, but I don't know how to share it later.
Sample Code download: IL-3