假设我们需要一个名叫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构造动态代理类

C#使用Emit生成构造函数和属性的更多相关文章

  1. MSIL实用指南-生成构造函数

    本篇讲解生成构造函数的一些知识,包括创建实例构造函数.静态构造函数.调用父类构造函数. 生成构造函数的方法生成构造函数的方法是TypeBuilder.DefineConstructor(MethodA ...

  2. eclipse中如何自动生成构造函数

    eclipse中如何自动生成构造函数 eclipse是一个非常好的IDE,我在写java程序的时候使用eclipse感觉开发效率很高.而且有很多的快捷和简便方式供大家使用,并且能直接生成class文件 ...

  3. 如何快速编写和调试 Emit 生成 IL 的代码

    .NET Core/.NET Framework 的 System.Reflection.Emit 命名空间为我们提供了动态生成 IL 代码的能力.利用这项能力,我们能够在运行时生成一段代码/一个方法 ...

  4. js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } Class ...

  5. Ninject依赖注入——构造函数、属性、方法和字段的注入

    Ninject依赖注入——构造函数.属性.方法和字段的注入(三) 1.Ninject简介 Ninject是基于.Net平台的依赖注入框架,它能够将应用程序分离成一个个高内聚.低耦合(loosely-c ...

  6. JavaScript 中实现继承的方式(列举3种在前一章,我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。)

    第一种:对象冒充 function ClassA(sColor) { this.color = sColor; this.sayColor = function () { alert(this.col ...

  7. js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } ClassA ...

  8. 使用 Emit 生成 IL 代码

    .NET Core/.NET Framework 的 System.Reflection.Emit 命名空间为我们提供了动态生成 IL 代码的能力.利用这项能力,我们能够在运行时生成一段代码/一个方法 ...

  9. 利用反射获取数据列+emit生成属性+单例模式

    1:IDictionary<string,string > 可以存储数据,将拼接的sql可以存储到这里下次可以使用 定义自定义属性表和列 typeof(T).GetCustomAttrib ...

随机推荐

  1. python骚操作之...

    python中的Ellipsis对象.写作:- 中文解释:省略 该对象bool测试是为真 用途: 1.用来省略代码,作用类似于pass的一种替代方案. from collections.abc imp ...

  2. Crypto++入门学习笔记(DES、AES、RSA、SHA-256)

    最先附上 下载地址 背景(只是个人感想,技术上不对后面的内容构成知识性障碍,可以skip): 最近,基于某些原因和需要,笔者需要去了解一下Crypto++库,然后对一些数据进行一些加密解密的操作. 笔 ...

  3. day2 --> pyc 文件

    执行python 代码时,如果导入了其他的.py文件,那么,执行过程中会自动生成一个与其同名的.pyc文件,该文件就是python解释器便宜之后产生的字节码. PS:代码经过便宜可以产生字节码;字节码 ...

  4. ubuntu 安装source insight3.5

    版本 ubuntu 16.04 在linux下安装 windows下程序,需要安装wine, wine 是 "“Wine Is Not an Emulator" 缩写. 1) 安装 ...

  5. Git系列①之仓库管理互联网托管平台github.com的使用

    互联网项目托管平台github.com的使用 1.安装git客户端 # yum install -y git 配置git全局用户以及邮箱 [root@web01 ~]# git config --gl ...

  6. Ex3_28 在2SAT问题中,给定一个字句的集合..._第十二次作业

    参考答案 ----------------------------------------------------------------------------------------------- ...

  7. js——作用域和闭包

    1. js是编译语言,但是它不是提前编译,编译结果不能在分布式系统中移植.大部分情况下,js的编译发生在代码执行前的几微秒(甚至更短) 2. 一般的编译步骤   分词/词法分析:把字符串分解成词法单元 ...

  8. 基于ARM Cortex-M和Eclipse的SWO单总线输出

    最近在MCU on Eclipse网站上看到Erich Styger所写的一篇有关通过SWD的跟踪接口SWO获取ARM Cortex-M相关信息的文章,文章结构明晰,讲解透彻,本人深受启发,特意将其翻 ...

  9. Java中关于string的些许问题及解析

    问题一:String 和 StringBuffer 的区别JAVA 平台提供了两个类: String 和 StringBuf fer ,它们可以储存和操作字符串,即包含多个字符的字符数据.这个 Str ...

  10. Confluence 6 缓存状态

    Confluence 为系统的内部缓存提供了缓存的状态以便于你对缓存的大小的命中率进行跟踪,在必要的情况下,你可以对缓存进行调整,让缓存能够更好的满足你的使用需求.请查看 Performance Tu ...