博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#使用Emit生成构造函数和属性
阅读量:4582 次
发布时间:2019-06-09

本文共 11060 字,大约阅读时间需要 36 分钟。

假设我们需要一个名叫Kitty的类,其在Pets程序集下。

1     // specify a new assembly name 2     var assemblyName = new AssemblyName("Pets"); 3  4     // create assembly builder 5     var assemblyBuilder = AppDomain.CurrentDomain 6       .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); 7  8     // create module builder 9     var moduleBuilder = assemblyBuilder.DefineDynamicModule("PetsModule", "Pets.dll");10 11     // create type builder for a class12     var typeBuilder = moduleBuilder.DefineType("Kitty", TypeAttributes.Public);

定义字段

Kitty类包含两个私有字段_id和_name。用类型构造器来定义,

1     var fieldId = typeBuilder.DefineField(2       "_id", typeof(int), FieldAttributes.Private);3     var fieldName = typeBuilder.DefineField(4       "_name", typeof(string), FieldAttributes.Private);

定义构造函数

Kitty类包含一个有两个参数的构造函数,参数一为整型id,参数而为字符串型name。构造函数内,将参数id赋值给私有字段_id,将参数name赋值给私有字段_name,

1     Type objType = Type.GetType("System.Object"); 2     ConstructorInfo objCtor = objType.GetConstructor(new Type[0]); 3  4     Type[] constructorArgs = { typeof(int), typeof(string) }; 5  6     var constructorBuilder = typeBuilder.DefineConstructor( 7         MethodAttributes.Public, CallingConventions.Standard, constructorArgs); 8     ILGenerator ilOfCtor = constructorBuilder.GetILGenerator(); 9 10     ilOfCtor.Emit(OpCodes.Ldarg_0);11     ilOfCtor.Emit(OpCodes.Call, objCtor);12     ilOfCtor.Emit(OpCodes.Ldarg_0);13     ilOfCtor.Emit(OpCodes.Ldarg_1);14     ilOfCtor.Emit(OpCodes.Stfld, fieldId);15     ilOfCtor.Emit(OpCodes.Ldarg_0);16     ilOfCtor.Emit(OpCodes.Ldarg_2);17     ilOfCtor.Emit(OpCodes.Stfld, fieldName);18     ilOfCtor.Emit(OpCodes.Ret);

定义属性

为Kitty类创建Id和Name两个属性,读取和设置私有字段_id和_name。C#中的属性定义的getter和setter分别为两个方法。

1     var methodGetId = typeBuilder.DefineMethod( 2       "GetId", MethodAttributes.Public, typeof(int), null); 3     var methodSetId = typeBuilder.DefineMethod( 4       "SetId", MethodAttributes.Public, null, new Type[] { typeof(int) }); 5  6     var ilOfGetId = methodGetId.GetILGenerator(); 7     ilOfGetId.Emit(OpCodes.Ldarg_0); // this 8     ilOfGetId.Emit(OpCodes.Ldfld, fieldId); 9     ilOfGetId.Emit(OpCodes.Ret);10 11     var ilOfSetId = methodSetId.GetILGenerator();12     ilOfSetId.Emit(OpCodes.Ldarg_0); // this13     ilOfSetId.Emit(OpCodes.Ldarg_1); // the first one in arguments list14     ilOfSetId.Emit(OpCodes.Stfld, fieldId);15     ilOfSetId.Emit(OpCodes.Ret);16 17     // create Id property18     var propertyId = typeBuilder.DefineProperty(19       "Id", PropertyAttributes.None, typeof(int), null);20     propertyId.SetGetMethod(methodGetId);21     propertyId.SetSetMethod(methodSetId);22 23     var methodGetName = typeBuilder.DefineMethod(24       "GetName", MethodAttributes.Public, typeof(string), null);25     var methodSetName = typeBuilder.DefineMethod(26       "SetName", MethodAttributes.Public, null, new Type[] { typeof(string) });27 28     var ilOfGetName = methodGetName.GetILGenerator();29     ilOfGetName.Emit(OpCodes.Ldarg_0); // this30     ilOfGetName.Emit(OpCodes.Ldfld, fieldName);31     ilOfGetName.Emit(OpCodes.Ret);32 33     var ilOfSetName = methodSetName.GetILGenerator();34     ilOfSetName.Emit(OpCodes.Ldarg_0); // this35     ilOfSetName.Emit(OpCodes.Ldarg_1); // the first one in arguments list36     ilOfSetName.Emit(OpCodes.Stfld, fieldName);37     ilOfSetName.Emit(OpCodes.Ret);38 39     // create Name property40     var propertyName = typeBuilder.DefineProperty(41       "Name", PropertyAttributes.None, typeof(string), null);42     propertyName.SetGetMethod(methodGetName);43     propertyName.SetSetMethod(methodSetName);

定义方法

为Kitty类增加一个ToString()方法,返回一个字符串值。

1     // create ToString() method 2     var methodToString = typeBuilder.DefineMethod( 3       "ToString", 4       MethodAttributes.Virtual | MethodAttributes.Public, 5       typeof(string), 6       null); 7  8     var ilOfToString = methodToString.GetILGenerator(); 9     var local = ilOfToString.DeclareLocal(typeof(string)); // create a local variable10     ilOfToString.Emit(OpCodes.Ldstr, "Id:[{0}], Name:[{1}]");11     ilOfToString.Emit(OpCodes.Ldarg_0); // this12     ilOfToString.Emit(OpCodes.Ldfld, fieldId);13     ilOfToString.Emit(OpCodes.Box, typeof(int)); // boxing the value type to object14     ilOfToString.Emit(OpCodes.Ldarg_0); // this15     ilOfToString.Emit(OpCodes.Ldfld, fieldName);16     ilOfToString.Emit(OpCodes.Call,17       typeof(string).GetMethod("Format",18       new Type[] { typeof(string), typeof(object), typeof(object) }));19     ilOfToString.Emit(OpCodes.Stloc, local); // set local variable20     ilOfToString.Emit(OpCodes.Ldloc, local); // load local variable to stack21     ilOfToString.Emit(OpCodes.Ret);

保存类型

生成类型,并保存程序集至Pets.dll文件。

1     // then create the whole class type2     var classType = typeBuilder.CreateType();3 4     // save assembly5     assemblyBuilder.Save("Pets.dll");

反编译类

使用反编译器来查看生成的类,

1 using System; 2 public class Kitty 3 { 4   private int _id; 5   private string _name; 6   public int Id 7   { 8     get 9     {10       return this._id;11     }12     set13     {14       this._id = value;15     }16   }17   public string Name18   {19     get20     {21       return this._name;22     }23     set24     {25       this._name = value;26     }27   }28   public Kitty(int id, string name)29   {30     this._id = id;31     this._name = name;32   }33   public override string ToString()34   {35     return string.Format("Id:[{0}], Name:[{1}]", this._id, this._name);36   }37 }

完整代码

1 using System;  2 using System.Reflection;  3 using System.Reflection.Emit;  4   5 namespace EmitCreateMembers  6 {  7   class Program  8   {  9     static void Main(string[] args) 10     { 11       // specify a new assembly name 12       var assemblyName = new AssemblyName("Pets"); 13  14       // create assembly builder 15       var assemblyBuilder = AppDomain.CurrentDomain 16         .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); 17  18       // create module builder 19       var moduleBuilder = assemblyBuilder.DefineDynamicModule("PetsModule", "Pets.dll"); 20  21       // create type builder for a class 22       var typeBuilder = moduleBuilder.DefineType("Kitty", TypeAttributes.Public); 23  24       // then create whole class structure 25       CreateKittyClassStructure(typeBuilder); 26  27       // then create the whole class type 28       var classType = typeBuilder.CreateType(); 29  30       // save assembly 31       assemblyBuilder.Save("Pets.dll"); 32  33       Console.WriteLine("Hi, Dennis, a Pets assembly has been generated for you."); 34       Console.ReadLine(); 35     } 36  37     private static void CreateKittyClassStructure(TypeBuilder typeBuilder) 38     { 39       // ---- define fields ---- 40  41       var fieldId = typeBuilder.DefineField( 42         "_id", typeof(int), FieldAttributes.Private); 43       var fieldName = typeBuilder.DefineField( 44         "_name", typeof(string), FieldAttributes.Private); 45  46       // ---- define costructors ---- 47  48       Type objType = Type.GetType("System.Object"); 49       ConstructorInfo objCtor = objType.GetConstructor(new Type[0]); 50  51       Type[] constructorArgs = { typeof(int), typeof(string) }; 52  53       var constructorBuilder = typeBuilder.DefineConstructor( 54          MethodAttributes.Public, CallingConventions.Standard, constructorArgs); 55       ILGenerator ilOfCtor = constructorBuilder.GetILGenerator(); 56  57       ilOfCtor.Emit(OpCodes.Ldarg_0); 58       ilOfCtor.Emit(OpCodes.Call, objCtor); 59       ilOfCtor.Emit(OpCodes.Ldarg_0); 60       ilOfCtor.Emit(OpCodes.Ldarg_1); 61       ilOfCtor.Emit(OpCodes.Stfld, fieldId); 62       ilOfCtor.Emit(OpCodes.Ldarg_0); 63       ilOfCtor.Emit(OpCodes.Ldarg_2); 64       ilOfCtor.Emit(OpCodes.Stfld, fieldName); 65       ilOfCtor.Emit(OpCodes.Ret); 66  67       // ---- define properties ---- 68  69       var methodGetId = typeBuilder.DefineMethod( 70         "GetId", MethodAttributes.Public, typeof(int), null); 71       var methodSetId = typeBuilder.DefineMethod( 72         "SetId", MethodAttributes.Public, null, new Type[] { typeof(int) }); 73  74       var ilOfGetId = methodGetId.GetILGenerator(); 75       ilOfGetId.Emit(OpCodes.Ldarg_0); // this 76       ilOfGetId.Emit(OpCodes.Ldfld, fieldId); 77       ilOfGetId.Emit(OpCodes.Ret); 78  79       var ilOfSetId = methodSetId.GetILGenerator(); 80       ilOfSetId.Emit(OpCodes.Ldarg_0); // this 81       ilOfSetId.Emit(OpCodes.Ldarg_1); // the first one in arguments list 82       ilOfSetId.Emit(OpCodes.Stfld, fieldId); 83       ilOfSetId.Emit(OpCodes.Ret); 84  85       // create Id property 86       var propertyId = typeBuilder.DefineProperty( 87         "Id", PropertyAttributes.None, typeof(int), null); 88       propertyId.SetGetMethod(methodGetId); 89       propertyId.SetSetMethod(methodSetId); 90  91       var methodGetName = typeBuilder.DefineMethod( 92         "GetName", MethodAttributes.Public, typeof(string), null); 93       var methodSetName = typeBuilder.DefineMethod( 94         "SetName", MethodAttributes.Public, null, new Type[] { typeof(string) }); 95  96       var ilOfGetName = methodGetName.GetILGenerator(); 97       ilOfGetName.Emit(OpCodes.Ldarg_0); // this 98       ilOfGetName.Emit(OpCodes.Ldfld, fieldName); 99       ilOfGetName.Emit(OpCodes.Ret);100 101       var ilOfSetName = methodSetName.GetILGenerator();102       ilOfSetName.Emit(OpCodes.Ldarg_0); // this103       ilOfSetName.Emit(OpCodes.Ldarg_1); // the first one in arguments list104       ilOfSetName.Emit(OpCodes.Stfld, fieldName);105       ilOfSetName.Emit(OpCodes.Ret);106 107       // create Name property108       var propertyName = typeBuilder.DefineProperty(109         "Name", PropertyAttributes.None, typeof(string), null);110       propertyName.SetGetMethod(methodGetName);111       propertyName.SetSetMethod(methodSetName);112 113       // ---- define methods ----114 115       // create ToString() method116       var methodToString = typeBuilder.DefineMethod(117         "ToString",118         MethodAttributes.Virtual | MethodAttributes.Public,119         typeof(string),120         null);121 122       var ilOfToString = methodToString.GetILGenerator();123       var local = ilOfToString.DeclareLocal(typeof(string)); // create a local variable124       ilOfToString.Emit(OpCodes.Ldstr, "Id:[{0}], Name:[{1}]");125       ilOfToString.Emit(OpCodes.Ldarg_0); // this126       ilOfToString.Emit(OpCodes.Ldfld, fieldId);127       ilOfToString.Emit(OpCodes.Box, typeof(int)); // boxing the value type to object128       ilOfToString.Emit(OpCodes.Ldarg_0); // this129       ilOfToString.Emit(OpCodes.Ldfld, fieldName);130       ilOfToString.Emit(OpCodes.Call,131         typeof(string).GetMethod("Format",132         new Type[] { typeof(string), typeof(object), typeof(object) }));133       ilOfToString.Emit(OpCodes.Stloc, local); // set local variable134       ilOfToString.Emit(OpCodes.Ldloc, local); // load local variable to stack135       ilOfToString.Emit(OpCodes.Ret);136     }137   }138 }

转载于:https://www.cnblogs.com/twinhead/p/9160975.html

你可能感兴趣的文章
Collection接口的子接口——Queue接口
查看>>
LINUX安装NGINX
查看>>
服务器启动项目抛错 没有到主机的路由
查看>>
python_85_sys模块
查看>>
第九周动手动脑
查看>>
HDU 1811 Rank of Tetris
查看>>
winform 获取当前名称
查看>>
MyBatis笔记一:GettingStart
查看>>
查找不同的木棍
查看>>
面试题:顺时针打印矩阵
查看>>
DataSet、DataTable、DataRow、DataColumn区别及使用实例
查看>>
python 特殊方法
查看>>
Python3 练习笔记四
查看>>
装箱问题
查看>>
Android线程管理(一)——线程通信
查看>>
vim 使用技巧
查看>>
面向对象的特征有哪些方面?
查看>>
三月十一号
查看>>
国外免费空间
查看>>
构建linux内核树
查看>>