反射(Reflection)讓程式在執行時期檢查、操作組件、模組、類型、成員(欄位、屬性、方法、事件)的中繼資料,並支援動態建立實例、呼叫方法、存取屬性。核心命名空間:System.Reflection。
| 類別 | 用途 |
|---|---|
Assembly | 載入組件、列舉型別、取得資源 |
Type | 型別中繼資料核心,取得建構函式、方法、屬性、欄位 |
MethodInfo | 方法資訊,Invoke(obj, params) 動態呼叫 |
ConstructorInfo | 建構函式資訊,Invoke(params) 動態實例化 |
PropertyInfo / FieldInfo | 屬性/欄位資訊,GetValue/SetValue 存取 |
EventInfo | 事件資訊,動態加入/移除處理器 |
// Example25Lib.dll
namespace Example25Lib {
public class Class1 {
private string _name;
private int _age;
public Class1(string name, int age) { _name = name; _age = age; }
public void ChangeName(string newName) => _name = newName;
public void ChangeAge(int newAge) => _age = newAge;
public override string ToString() => $"Name: {_name}, Age: {_age}";
}
}
using System;
using System.Reflection;
namespace Example25 {
class Program {
static void Main() {
// 1. 載入組件(絕對路徑)
string dllPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Example25Lib.dll");
Assembly asm = Assembly.LoadFile(dllPath);
// 2. 列舉所有公開類型
foreach (Type type in asm.GetTypes()) {
Console.WriteLine($"發現類型: {type.FullName}");
// 3. 取得所有公開建構函式
foreach (ConstructorInfo ctor in type.GetConstructors()) {
// 4. 準備建構函式參數
ParameterInfo[] ctorParams = ctor.GetParameters();
object[] args = new object[ctorParams.Length];
for (int i = 0; i < ctorParams.Length; i++) {
Type pt = ctorParams[i].ParameterType;
if (pt == typeof(string)) args[i] = "Clark";
else if (pt == typeof(int)) args[i] = 0;
else args[i] = Activator.CreateInstance(pt); // 嘗試預設建構
}
// 5. 動態實例化
object instance = ctor.Invoke(args);
Console.WriteLine($"實例化: {instance}");
// 6. 取得所有公開方法並呼叫
foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
ParameterInfo[] mParams = method.GetParameters();
object[] mArgs = new object[mParams.Length];
for (int i = 0; i < mParams.Length; i++) {
Type pt = mParams[i].ParameterType;
if (pt == typeof(string)) mArgs[i] = "Clark Zheng";
else if (pt == typeof(int)) mArgs[i] = 27;
else mArgs[i] = Activator.CreateInstance(pt);
}
method.Invoke(instance, mArgs);
}
// 7. 再次輸出驗證狀態變更
Console.WriteLine($"呼叫後: {instance}");
}
}
Console.ReadLine();
}
}
}
發現類型: Example25Lib.Class1
實例化: Name: Clark, Age: 0
呼叫後: Name: Clark Zheng, Age: 27
[Test] 屬性標記的方法MethodInfo/PropertyInfo、使用 Delegate.CreateDelegate 或 Expression Tree 編譯委託。ReflectionPermission 控管私有成員存取;沙箱環境可能受限。[DynamicDependency] 或保留屬性。// 假設已取得 MethodInfo method
var func = (Func