反射 是 .NET 運行時檢查、操作類型中繼資料的機制。核心類位於 System.Reflection:
Assembly:程序集,可加載、檢查、創建類型實例Type:類型核心,包含方法、屬性、構造函數、字段等完整描述MethodInfo、PropertyInfo、FieldInfo、ConstructorInfo...:具體成員資訊MyClass obj = new MyClass();
// 1. 實例.GetType()
Type t1 = obj.GetType();
// 2. typeof(類型) - 編譯期已知
Type t2 = typeof(MyClass);
// 3. 字串獲取 - 完全動態
Type t3 = Type.GetType("MyNamespace.MyClass, MyAssembly");
Console.WriteLine($"名稱: {t.Name}");
Console.WriteLine($"完整名: {t.FullName}");
Console.WriteLine($"命名空間: {t.Namespace}");
Console.WriteLine($"程序集: {t.Assembly}");
Console.WriteLine($"基類: {t.BaseType}");
Console.WriteLine($"是否類: {t.IsClass}");
// 獲取所有公共成員
foreach (var m in t.GetMembers())
Console.WriteLine($"{m.MemberType}: {m.Name}");
Assembly asm = Assembly.GetExecutingAssembly();
Console.WriteLine($"完整名: {asm.FullName}");
Console.WriteLine($"版本: {asm.GetName().Version}");
Console.WriteLine($"位置: {asm.Location}");
Console.WriteLine($"入口點: {asm.EntryPoint}");
// 列出程序集所有類型
foreach (var type in asm.GetTypes())
Console.WriteLine($"類型: {type.FullName}");
// 從文件加載
Assembly asm = Assembly.LoadFrom(@"C:\Libs\MyPlugin.dll");
// 從字節數組加載 (如從資料庫/網絡獲取)
byte[] dllBytes = File.ReadAllBytes("Plugin.dll");
Assembly asm = Assembly.Load(dllBytes);
早綁定 = 編譯期確定類型;晚綁定 = 運行時根據字串決定類型與成員。
public class Calculator
{
private readonly int _factor;
public Calculator(int factor) => _factor = factor;
public int Multiply(int x) => x * _factor;
}
// Main
Assembly asm = Assembly.GetExecutingAssembly();
// 1. 創建實例 (帶構造函數參數)
object calc = asm.CreateInstance(
"MyApp.Calculator",
false,
BindingFlags.ExactBinding,
null,
new object[] { 5 }, // 構造參數
null, null);
// 2. 獲取方法資訊
MethodInfo method = asm.GetType("MyApp.Calculator").GetMethod("Multiply");
// 3. 調用方法
object result = method.Invoke(calc, new object[] { 10 });
Console.WriteLine($"結果: {result}"); // 50
| 場景 | 核心 API | 說明 |
|---|---|---|
| 插件掃描 | Assembly.LoadFrom + GetExportedTypes | 掃描目錄 DLL 載入擴展 |
| 配置驅動實例化 | Type.GetType + Activator.CreateInstance | 字串名稱創建對象 |
| 動態方法調用 | MethodInfo.Invoke | 運行時決定調用哪個方法 |
| 屬性值獲取/設置 | PropertyInfo.GetValue/SetValue | 序列化、映射、綁定核心 |
| 自定義特性讀取 | GetCustomAttributes | 框架基礎設施 |
MethodInfo/PropertyInfo,或用 Delegate.CreateDelegate 轉為委托BindingFlags 組合控制搜索範圍:Public | NonPublic | Instance | Static | FlattenHierarchyReflectionPermissionGetType()/GetProperties()對於頻繁動態調用,System.Linq.Expressions 可在運行時編譯委托,性能接近靜態代碼:
var param = Expression.Parameter(typeof(Calculator), "c");
var call = Expression.Call(param, "Multiply", null, Expression.Constant(10));
var lambda = Expression.Lambda<Func<Calculator, int>>(call, param);
var compiled = lambda.Compile(); // 快速委托
int result = compiled(calc);
反射是 .NET 動態能力的基石,理解 Type/Assembly/晚綁定三大支柱,才能駕馭框架開發與進階架構設計。