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