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();

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM