public class User { public int Id { get; set; } private string _name; public string Name { get=>_name; set=>_name=value; } }
var user = new User();
Type t = user.GetType(); // 或 typeof(User)
// 讀寫公開屬性
PropertyInfo pId = t.GetProperty("Id");
pId.SetValue(user, 101);
int id = (int)pId.GetValue(user);
// 讀寫私有欄位(需 BindingFlags)
FieldInfo fName = t.GetField("_name", BindingFlags.NonPublic | BindingFlags.Instance);
fName.SetValue(user, "Alice");
string name = (string)fName.GetValue(user);
// 簽章
object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args);
// 實例化(無參建構子)
object obj = t.InvokeMember(null, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, null, null, null);
// 呼叫無回傳方法
t.InvokeMember("Display", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, new[] { "Hello" });
// 呼叫有回傳方法
int result = (int)t.InvokeMember("Add", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { 1, 2 });
// 讀寫屬性
t.InvokeMember("Name", BindingFlags.SetProperty, null, obj, new[] { "Bob" });
string n = (string)t.InvokeMember("Name", BindingFlags.GetProperty, null, obj, null);
// 讀寫欄位
t.InvokeMember("_name", BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance, null, obj, new[] { "Bob" });
string fn = (string)t.InvokeMember("_name", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null, obj, null);
| 旗標 | 用途 |
|---|---|
Public | Instance | 預設,公開實例成員 |
NonPublic | Instance | 私有/受保護實例成員 |
Static | 靜態成員 |
FlattenHierarchy | 包含繼承鏈靜態成員 |
IgnoreCase | 名稱大小寫不敏感 |
DeclaredOnly | 僅本類別宣告,不含繼承 |
反射每次呼叫約 100-500ns 開銷,高頻熱路徑請轉為委派:
// 靜態快取
static readonly Func GetId = (Func)Delegate.CreateDelegate(typeof(Func), typeof(User).GetProperty("Id").GetGetMethod());
static readonly Action SetId = (Action)Delegate.CreateDelegate(typeof(Action), typeof(User).GetProperty("Id").GetSetMethod());
// 使用
int id = GetId(user);
SetId(user, 202);
效能接近直接呼叫,且保持動態性。
System.Reflection.Metadata 讀取編譯時中繼資料,避免執行時反射。delegate* managed 函數指標(C# 9)可直接轉換方法指標,零配置。PropertyInfo、MethodInfo)靜態快取,勿重複 GetProperty。Delegate.CreateDelegate 或原始碼生成器。BindingFlags.NonPublic,注意信任層級限制(沙箱環境可能失效)。