C# Emit

一、反射发出(Emit)

  .Net允许编译器或工具在运行时发出元数据和 Microsoft 中间语言 (MSIL),并在磁盘上生成可移植可执行 (PE) 文件(可选)。相关的API在System.Reflection.Emit命名空间下。

反射发出具有一下功能:

  1.在运行时定义轻量全局方法(使用 DynamicMethod 类)并通过委托执行这些方法。

  2.在运行时定义程序集,然后运行程序集以及/或者将程序集保存到磁盘。

  3.在运行时定义程序集,运行程序集,然后卸载程序集并允许垃圾回收回收其资源。

  4.在运行时在新的程序集中定义模块,然后运行模块以及/或者将模块保存到磁盘。

  5.在运行时在模块中定义类型,创建这些类型的实例并调用其方法。

  6.为已定义模块定义可供工具(如调试器和代码探查器)使用的符号化信息。

二、定义和执行动态方法

  1.创建动态方法 方法名为SquareIt,返回值类型为long,参数列表为int

DynamicMethod squareIt = new DynamicMethod("SquareIt", typeof(long), new Type[] { typeof(int) }, typeof(Program).Module);

  2.生成IL代码,将参数 int 加载到堆栈,将其转换为 long,复制 long,然后将这两个数字相乘

// 生成IL代码,将参数(int)加载到堆栈
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // 将参数(int)加载到堆栈
il.Emit(OpCodes.Conv_I8); // 将int转换为long
il.Emit(OpCodes.Dup);// 复制堆栈顶部的值
il.Emit(OpCodes.Mul);// 堆栈上最上面的两个值相乘
il.Emit(OpCodes.Ret);// 返回

  3.通过调用 CreateDelegate 方法创建表示动态方法的委托,并执行此方法,并打印输出

// 将生成的动态方转换成委托类型
Func<int, long> invokeSquareIt = (Func<int, long>)squareIt.CreateDelegate(typeof(Func<int, long>));

// 执行动态方法
Console.WriteLine("9的平方 = {0}", invokeSquareIt(9));

  4.打印结果   

  

  5.完整的代码

static void Main(string[] args)
{

    // 创建动态方法 方法名为SquareIt,返回值类型为long,参数列表为int,
    DynamicMethod squareIt = new DynamicMethod("SquareIt", typeof(long), new Type[] { typeof(int) }, typeof(Program).Module);

    // 生成IL代码,将参数(int)加载到堆栈
    ILGenerator il = squareIt.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0); // 将参数(int)加载到堆栈
    il.Emit(OpCodes.Conv_I8); // 将int转换为long
    il.Emit(OpCodes.Dup);// 复制堆栈顶部的值
    il.Emit(OpCodes.Mul);// 堆栈上最上面的两个值相乘
    il.Emit(OpCodes.Ret);// 返回

    // 将生成的动态方转换成委托类型
    Func<int, long> invokeSquareIt = (Func<int, long>)squareIt.CreateDelegate(typeof(Func<int, long>));

    // 执行动态方法
    Console.WriteLine("9的平方 = {0}", invokeSquareIt(9));

}

 三、用Emit编写HelloWorld控制台

DynamicMethod method = new DynamicMethod("Main", null, Type.EmptyTypes);

//生成IL代码
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldstr, "Hello World!");
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
il.Emit(OpCodes.Ret);

//创建委托
Action helloWorldMethod =(Action) method.CreateDelegate(typeof(Action));

helloWorldMethod.Invoke();

 

 

posted @ 2022-03-24 11:28  Zeng。  阅读(958)  评论(0编辑  收藏  举报