C#使用Emit生成构造函数和属性-阿里云开发者社区

开发者社区> 嗯哼9925> 正文

C#使用Emit生成构造函数和属性

简介:
+关注继续查看

假设我们需要一个名叫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 class
12     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); // this
13     ilOfSetId.Emit(OpCodes.Ldarg_1); // the first one in arguments list
14     ilOfSetId.Emit(OpCodes.Stfld, fieldId);
15     ilOfSetId.Emit(OpCodes.Ret);
16 
17     // create Id property
18     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); // this
30     ilOfGetName.Emit(OpCodes.Ldfld, fieldName);
31     ilOfGetName.Emit(OpCodes.Ret);
32 
33     var ilOfSetName = methodSetName.GetILGenerator();
34     ilOfSetName.Emit(OpCodes.Ldarg_0); // this
35     ilOfSetName.Emit(OpCodes.Ldarg_1); // the first one in arguments list
36     ilOfSetName.Emit(OpCodes.Stfld, fieldName);
37     ilOfSetName.Emit(OpCodes.Ret);
38 
39     // create Name property
40     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 variable
10     ilOfToString.Emit(OpCodes.Ldstr, "Id:[{0}], Name:[{1}]");
11     ilOfToString.Emit(OpCodes.Ldarg_0); // this
12     ilOfToString.Emit(OpCodes.Ldfld, fieldId);
13     ilOfToString.Emit(OpCodes.Box, typeof(int)); // boxing the value type to object
14     ilOfToString.Emit(OpCodes.Ldarg_0); // this
15     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 variable
20     ilOfToString.Emit(OpCodes.Ldloc, local); // load local variable to stack
21     ilOfToString.Emit(OpCodes.Ret);
复制代码

保存类型

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

1     // then create the whole class type
2     var classType = typeBuilder.CreateType();
3 
4     // save assembly
5     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     set
13     {
14       this._id = value;
15     }
16   }
17   public string Name
18   {
19     get
20     {
21       return this._name;
22     }
23     set
24     {
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); // this
103       ilOfSetName.Emit(OpCodes.Ldarg_1); // the first one in arguments list
104       ilOfSetName.Emit(OpCodes.Stfld, fieldName);
105       ilOfSetName.Emit(OpCodes.Ret);
106 
107       // create Name property
108       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() method
116       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 variable
124       ilOfToString.Emit(OpCodes.Ldstr, "Id:[{0}], Name:[{1}]");
125       ilOfToString.Emit(OpCodes.Ldarg_0); // this
126       ilOfToString.Emit(OpCodes.Ldfld, fieldId);
127       ilOfToString.Emit(OpCodes.Box, typeof(int)); // boxing the value type to object
128       ilOfToString.Emit(OpCodes.Ldarg_0); // this
129       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 variable
134       ilOfToString.Emit(OpCodes.Ldloc, local); // load local variable to stack
135       ilOfToString.Emit(OpCodes.Ret);
136     }
137   }
138 }
复制代码

下载完整代码

进一步了解使用Emit构造动态代理类

 





本文转自匠心十年博客园博客,原文链接:http://www.cnblogs.com/gaochundong/archive/2013/06/01/csharp_emit_create_constructor_properties.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用Source Monitor检测Java代码的环复杂度
使用Source Monitor检测Java代码的环复杂度
3 0
LINUX C# 加载本地库的范例代码
LINUX C# 加载本地库的范例代码
3 0
这些杰出顶尖的女性程序媛,你认识几个?
  埃达?洛夫莱斯(Ada Lovelace Byron),全名为奥古斯塔?埃达?金,洛夫莱斯伯爵夫人,1815年12月10日-1852年11月27日),著名英国诗人拜伦之女,她被后世公认为是第一位计算机程序员。她死后一百年,于1953年,埃达之前对查尔斯?巴贝奇的《分析机概论》所留下的笔记被重新公布,并被认为对现代计算机与软件工程造成了重大影响。   葛丽丝?穆雷?霍普(1906年12月9日-1992年1月1日,生于美国纽约,美国海军准将及计算机科学家,世界最早一批的程序员之一,也是最早的女性程序员之一。她创造了现代第一个编译器A-0系统,以及第一个高级商用计算机程序语言“COBOL”
3 0
Script Lab 版,九九乘法表,Excel 基础操作(2)
Script Lab 版,九九乘法表,Excel 基础操作(2)
5 0
LINUX C#开发图形界面代码范例及编译
LINUX C#开发图形界面代码范例及编译
5 0
LINUX C#安装开发工具MonoDevelop
LINUX C#安装开发工具MonoDevelop
5 0
LINUX上编译C#开发环境Mono
LINUX上编译C#开发环境Mono
5 0
关于C# yield 你会使用吗?
假设有这样一个需求:在一个数据源(下面代码arry)中把其中大于4的数据取出来遍历到前台,怎么做?(不使用linq)
4 0
目标URL存在跨站漏洞
目标URL存在跨站漏洞
7 0
再来看看Dotnet的垃圾回收
  在说垃圾回收之前,先说说两个概念:   托管代码,是由CLR管理的代码非托管代码,是由操作系统直接执行的代码   在早期C++的时候,内存分配和释放都是由我们手动处理的,而在公共语言进行时CLR中,多了一个垃圾收集器GC,来充当自动内存管理器,完成同样的工作。从此,对于开发人员来说,我们可以不需要用显式的代码来执行内存管理。这样做的好处是明显的:大量相关内存的错误被消除了,比方没有释放对象导致的内存泄露,或试图访问已经释放的对象的内存,等等。
4 0
+关注
4716
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载