Emit动态生成代码

引用:秒懂C#通过Emit动态生成代码

首先需要声明一个程序集名称,

// specify a new assembly name
var assemblyName = new AssemblyName("Kitty");

从当前应用程序域获取程序集构造器,

// create assembly builder
var assemblyBuilder=AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

有几种动态程序集构造访问限制:

  • AssemblyBuilderAccess.Run; 表示程序集可被执行,但不能被保存。  
  • AssemblyBuilderAccess.Save; 表示程序集可被保存,但不能被执行。  
  • AssemblyBuilderAccess.RunAndSave; 表示程序集可被保存并能被执行。
  • AssemblyBuilderAccess.ReflectionOnly; 表示程序集只能用于反射上下文环境中,不能被执行。 
  • AssemblyBuilderAccess.RunAndCollect; 表示程序集可以被卸载并且内存会被回收。

在程序集中构造动态模块,

// create module builder
var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");

模块即是代码的集合,一个程序集中可以有多个模块。并且理论上讲,每个模块可以使用不同的编程语言实现,例如C#/VB。
构造一个类型构造器,

// create type builder for a class
var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);

通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。

// create method builder
var methodBuilder = typeBuilder.DefineMethod(
"SayHelloMethod",
MethodAttributes.Public | MethodAttributes.Static,
null,
null); // then get the method il generator
var il = methodBuilder.GetILGenerator(); // then create the method function
il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
il.Emit(OpCodes.Call,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));
il.Emit(OpCodes.Pop); // we just read something here, throw it.
il.Emit(OpCodes.Ret);

创建类型,

// then create the whole class type
var helloKittyClassType = typeBuilder.CreateType();

如果当前程序集是可运行的,则设置一个程序入口,

// set entry point for this assembly
assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));

将动态生成的程序集保存成磁盘文件,

// save assembly
assemblyBuilder.Save("Kitty.exe");

此时,通过反编译工具,将Kitty.exe反编译成代码,

using System;

public class HelloKittyClass
{
public static void SayHelloMethod()
{
Console.WriteLine("Hello, Kitty!");
Console.ReadLine();
}
}

运行结果,

完整代码

using System;
using System.Reflection;
using System.Reflection.Emit; namespace EmitIntroduction
{
class Program
{
static void Main(string[] args)
{
// specify a new assembly name
var assemblyName = new AssemblyName("Kitty"); // create assembly builder
var assemblyBuilder = AppDomain.CurrentDomain
.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave); // create module builder
var moduleBuilder =
assemblyBuilder.DefineDynamicModule(
"KittyModule", "Kitty.exe"); // create type builder for a class
var typeBuilder =
moduleBuilder.DefineType(
"HelloKittyClass", TypeAttributes.Public); // create method builder
var methodBuilder = typeBuilder.DefineMethod(
"SayHelloMethod",
MethodAttributes.Public | MethodAttributes.Static,
null,
null); // then get the method il generator
var il = methodBuilder.GetILGenerator(); // then create the method function
il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
il.Emit(OpCodes.Call,
typeof(Console).GetMethod(
"WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Call,
typeof(Console).GetMethod("ReadLine"));
il.Emit(OpCodes.Pop); // we just read something here, throw it.
il.Emit(OpCodes.Ret); // then create the whole class type
var helloKittyClassType = typeBuilder.CreateType(); // set entry point for this assembly
assemblyBuilder.SetEntryPoint(
helloKittyClassType.GetMethod("SayHelloMethod")); // save assembly
assemblyBuilder.Save("Kitty.exe"); Console.WriteLine(
"Hi, Dennis, a Kitty assembly has been generated for you.");
Console.ReadLine();
}
}
}

下载完整代码

进一步阅读使用Emit生成构造函数和属性

最新文章

  1. Python 黑帽编程大纲(变化中)
  2. jQuery学习笔记(四)jQuery中的动画
  3. 第三节 Hello world --python初体验
  4. Linux系统编程温故知新系列 --- 01
  5. UVA3026Period(最短循环节)
  6. python mysql
  7. [慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
  8. empty()和isset()的区别
  9. karma+angular
  10. Blogilo:Ubuntu下“wlw”
  11. OpenJudg / Poj 1363 Rails
  12. Java面向对象面试案例
  13. C#连接Oracle数据库基本类
  14. UI 公钥加密
  15. 移动端rem适配问题
  16. 4.编写Java应用程序。首先,定义一个时钟类——Clock,它包括三个int型 成员变量分别表示时、分、秒,一个构造方法用于对三个成员变量(时、分、秒) 进行初始化,还有一个成员方法show()用于显示时钟对象的时间。其次,再定义 一个主类——TestClass,在主类的main方法中创建多个时钟类的对象,使用这 些对象调用方法show()来显示时钟的时间。
  17. EntityFrameworkCore使用Migrations自动更新数据库
  18. Asp.net Authorization 学习
  19. python print 在windows上 出现 Bad file descriptor error
  20. JS流程控制

热门文章

  1. Android编译错误, Ignoring InnerClasses attribute for an anonymous inner class
  2. JqueryEasyUI浅谈本地化应用
  3. IPv6协议
  4. Kindle 转换器
  5. unity3D——自带寻路Navmesh入门教程(二)(转)
  6. AngularJS快速入门指南11:事件
  7. mysql悲观锁总结和实践
  8. linux(CentOS)-nodejs项目部署
  9. Atitit.api参数传递的设计
  10. springMVC乱码问题-转