System.Reflection.Emit 最輕量的切入點是 DynamicMethod——無需創建程序集/模塊/類型,直接在內存生成靜態方法並通過委托執行。本文以經典「Hello World」演示核心 API:DynamicMethod、ILGenerator、OpCodes、CreateDelegate。
using System;
using System.Reflection.Emit;
namespace EmitExamples.HelloWorld
{
class Program
{
private delegate void HelloWorldDelegate();
static void Main()
{
// 1. 定義動態方法:無返回值、無參數
var helloMethod = new DynamicMethod("HelloWorld", null, null);
// 2. 獲取 IL 生成器
var il = helloMethod.GetILGenerator();
// 3. 發射指令
il.Emit(OpCodes.Ldstr, "Hello World!"); // 壓入字符串
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); // 調用 Console.WriteLine
il.Emit(OpCodes.Ret); // 返回
// 4. 創建委托並執行
var hello = (HelloWorldDelegate)helloMethod.CreateDelegate(typeof(HelloWorldDelegate));
hello(); // 輸出: Hello World!
}
}
}
(name, returnType, parameterTypes, ownerModule/ownerType)。傳 null 表示無參無返回,最後參數可指定關聯模塊以訪問 internal 成員。OpCode 及可選操作數。Ldstr 專用於字符串字面量。OpCodes.Call 調用靜態方法 Console.WriteLine(string),需通過反射獲取 MethodInfo。var addMethod = new DynamicMethod("Add", typeof(int), new[] { typeof(int), typeof(int) });
var il = addMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ret);
var add = (Func<int, int, int>)addMethod.CreateDelegate(typeof(Func<int, int, int>));
Console.WriteLine(add(3, 5)); // 8
| 特性 | DynamicMethod | AssemblyBuilder |
|---|---|---|
| 持久化 | ❌ 僅內存 | ✅ 可保存 .dll |
| 類型定義 | ❌ 僅方法 | ✅ 完整類型系統 |
| 訪問非公有成員 | ✅ 關聯模塊可訪問 internal | ✅ 同程序集可訪問 |
| 適用場景 | 輕量級動態委托、表達式樹編譯 | 動態代理、ORM、編譯器後端 |
ildasm /text DynamicMethod.dll 查看 IL (需先保存為模塊)。DebuggableAttribute)。CreateDelegate 或調用時拋 VerificationException,善用 peverify。掌握 DynamicMethod,你就擁有了運行時生成高性能委托的鑰匙,這是表達式樹、動態代理、序列化庫的核心基石。