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

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

定义字段

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

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

定义构造函数

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

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

定义属性

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

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

定义方法

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

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

保存类型

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

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

反编译类

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

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

完整代码

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

    1批量插入数据: User_list=[]for i in range(100): User_list.append(User(name='小明%s'%i,pwd='abcdefg%s'%i))# 两 ...

  2. SSH localhost免密不成功 + 集群状态显示Configured Capacity: 0 (0 KB)

    前一天运行hadoop一切安好,今天重新运行出现BUG.下面对遇到的bug.产生原因以及解决方法进行一下简单总结记录. [bug1]用ssh localhost免密登录时提示要输入密码. 原因分析:之 ...

  3. bash的快捷键、特殊参数、历史命令、相关文件

    bash快捷键 Emacs风格 ctrl+p: 方向键 上 ↑ ctrl+n: 方向键下 ↓ ctrl+b: 方向键 ← alt+f: 光标右移一个单词 ctrl+f :方向键 → alt+b: 光标 ...

  4. 【原创】运维基础之Docker(5)docker部署airflow

    部署方式:docker+airflow+mysql+LocalExecutor 使用airflow的docker镜像 https://hub.docker.com/r/puckel/docker-ai ...

  5. 根据CAS协议写的简单的SSO框架

      前言: 考虑到现在分布式应用都不可或缺的一个重要部分:单点登录,决定花点时间去学下.本来想直接上现成的CAS框架的,初步的了解了一下后,觉得这个太庞大了,而且不好定制,要完全深度用起来也没那么简单 ...

  6. Java+selenium chrome 常见的问题WebDriverException: unknown error: call function result missing 'value'

    运行chrome浏览器 报错:"main" org.openqa.selenium.WebDriverException: unknown error: call function ...

  7. orm分组,聚合查询,执行原生sql语句

    from django.db.models import Avg from app01 import models annotate:(聚合查询) ret=models.Article.objects ...

  8. Python基础-入门之路PYTHON-包 相对导入&绝对导入

    什么是包 包也是一种模块,但本质上就是一个文件夹 对于使用者而言 使用方式和模块没有任何区别 本质上就是一个文件夹 不同之处在于 多了一个__init__.py 叫包的初始化文件 import导入模块 ...

  9. LuoGu P2735 电网 Electric Fences

    题目传送门 这个东西,本来我是用求出两条一次函数解析式然后判断在x坐标下的y坐标值来做的 首先因为没考虑钝角三角形,WA了 然后又因为精度处理不好又WA了 一气之下,只能去网上查了查那个皮克定理 首先 ...

  10. Oracle Database 11g : SQL 基础

    简介 1:课程目标 2:课程 目标 3:Oracle Database 11g 以及相关产品概览 1:Oracle Database 11g :重点领域 2:Oracle Fusion Middlew ...