反射是 .NET 執行期型別發現機制,允許程式碼檢查、操作組件、模組、型別、成員的中繼資料。本文系統整理 System.Reflection 命名空間核心類型、System.Type 類別關鍵成員、以及取得 Type 實例的三種方式。
| 類型 | 用途 | 關鍵屬性/方法 |
|---|---|---|
| Assembly | 載入、檢查、操作組件 | GetTypes(), GetName(), Load() |
| AssemblyName | 組件身分資訊 (版本、文化特性、強名稱) | Version, CultureInfo, GetPublicKey() |
| EventInfo | 事件中繼資料 | EventHandlerType, AddEventHandler() |
| FieldInfo | 欄位中繼資料 | FieldType, GetValue(), SetValue() |
| MethodInfo | 方法中繼資料 | ReturnType, GetParameters(), Invoke() |
| ParameterInfo | 參數中繼資料 | ParameterType, Name, Position |
| PropertyInfo | 屬性中繼資料 | PropertyType, GetValue(), SetValue() |
| MemberInfo | 抽象基類,定義共同行為 | Name, DeclaringType, MemberType, GetCustomAttributes() |
| Module | 多檔案組件中的模組存取 | GetTypes(), Assembly |
MemberInfo (abstract)
├── EventInfo
├── FieldInfo
├── MethodBase (abstract)
│ ├── ConstructorInfo
│ └── MethodInfo
├── PropertyInfo
└── Type (繼承 MemberInfo,也代表型別本身)
IsAbstract, IsClass, IsValueType, IsInterface, IsEnum,
IsArray, IsGenericType, IsGenericTypeDefinition,
IsPublic, IsPrivate, IsSealed, IsStatic, ...
// 單數版本:取得單一成員
GetConstructor(), GetEvent(), GetField(), GetMethod(), GetProperty()
// 複數版本:取得成員陣列
GetConstructors(), GetEvents(), GetFields(), GetMethods(), GetProperties()
// 統一查詢
FindMembers(MemberTypes, BindingFlags, MemberFilter, object)
GetMembers(BindingFlags)
// 從字串取得型別 (需完整命名空間)
Type.GetType("System.String") // mscorlib
Type.GetType("MyNamespace.MyClass, MyAssembly") // 指定組件
// 呼叫方法、存取屬性/欄位、建構實例
InvokeMember(string name, BindingFlags, Binder, object target, object[] args)
Person p = new Person();
Type t = p.GetType(); // 最常用,執行期確切型別
Type t1 = typeof(Person);
Type t2 = typeof(List);
Type t3 = typeof(Dictionary<,>); // 開放泛型型別定義
// 完整型別名稱:命名空間.類別名, 組件名稱
Type t = Type.GetType("MyApp.Models.Person, MyApp");
// 僅型別名稱:僅搜尋 mscorlib 與目前執行組件
Type t = Type.GetType("Person"); // 可能回傳 null
public static object CreateAndInvoke(string typeName, string methodName, params object[] args)
{
// 1. 取得型別
Type type = Type.GetType(typeName);
if (type == null) throw new ArgumentException($"找不到型別: {typeName}");
// 2. 建構實例 (呼叫無參數建構子)
object instance = Activator.CreateInstance(type);
// 3. 取得方法資訊
MethodInfo method = type.GetMethod(methodName);
if (method == null) throw new ArgumentException($"找不到方法: {methodName}");
// 4. 呼叫方法
return method.Invoke(instance, args);
}
// 使用
var result = CreateAndInvoke("MyApp.Services.Calculator", "Add", 10, 20);
// 相當於: new Calculator().Add(10, 20)
Type.GetType()、GetMethod()、GetProperty() 等反射操作較慢Expression Tree、DynamicMethod、Source Generators 替代System.Reflection 提供完整的中繼資料操作能力。核心在於 Type 類別作為入口,透過 MemberInfo 衍生類別存取具體成員。理解三種取得 Type 的方式、單數/複數成員查詢方法、晚期繫結 InvokeMember,是反射程式設計的基礎。實務中務必注意效能,善用快取與替代方案。