首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 反射命名空間 System.Reflection 深度解析

     編輯:關於C#

反射是 .NET 執行期型別發現機制的核心。System.Reflection 命名空間提供完整的 API,讓程式能檢視、操作組件、模組、型別與成員中繼資料。本文系統整理核心類別、Type 關鍵方法、取得 Type 實例的三種方式。

System.Reflection 核心類別架構

類別用途關鍵特性
Assembly 載入、檢視、操作組件 GetTypes(), GetManifestResourceStream(), Load()/LoadFrom()
AssemblyName 組件身分資訊 版本、文化特性、公開金鑰標記、完整名稱
Type 型別中繼資料核心 GetMethods(), GetProperties(), GetFields(), GetConstructors(), InvokeMember()
MemberInfo 所有成員的抽象基類 Name, DeclaringType, MemberType, GetCustomAttributes()
MethodInfo 方法中繼資料 ReturnType, GetParameters(), Invoke(), IsStatic, IsVirtual
PropertyInfo 屬性中繼資料 PropertyType, GetValue/SetValue, CanRead/CanWrite, GetIndexParameters()
FieldInfo 欄位中繼資料 FieldType, GetValue/SetValue, IsStatic, IsInitOnly, IsLiteral
EventInfo 事件中繼資料 EventHandlerType, AddEventHandler/RemoveEventHandler
ConstructorInfo 建構函式中繼資料 GetParameters(), Invoke(), IsStatic, IsPublic
ParameterInfo 參數中繼資料 ParameterType, Name, Position, DefaultValue, IsOptional
Module 多檔組件中的模組 GetTypes(), Assembly, FullyQualifiedName

Type 類別核心方法分類

1. 型別檢查:Is* 系列

type.IsClass        // 是否為類別
type.IsInterface    // 是否為介面
type.IsValueType    // 是否為實質型別
type.IsAbstract     // 是否為抽象
type.IsSealed       // 是否為密封
type.IsEnum         // 是否為列舉
type.IsArray        // 是否為陣列
type.IsGenericType  // 是否為泛型
type.IsPrimitive    // 是否為基本型別
type.IsPublic       // 是否為公開
type.IsNested       // 是否為巢狀型別

2. 成員取得:Get* 系列(單數/複數)

// 單數:取得特定名稱成員
type.GetMethod("MethodName")
type.GetProperty("PropertyName")
type.GetField("FieldName")
type.GetEvent("EventName")
type.GetConstructor(types)
type.GetMember("MemberName")

// 複數:取得所有符合條件成員
type.GetMethods(bindingFlags)
type.GetProperties(bindingFlags)
type.GetFields(bindingFlags)
type.GetEvents(bindingFlags)
type.GetConstructors(bindingFlags)
type.GetMembers(bindingFlags)
type.GetNestedTypes(bindingFlags)

3. 進階查詢與動態調用

// 依條件查詢成員
type.FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance, 
    Type.FilterName, "Get*");

// 靜態方法:依名稱取得 Type
Type.GetType("Namespace.ClassName")
Type.GetType("Namespace.ClassName, AssemblyName") // 跨組件
Type.GetType("Namespace.ClassName", false, true)  // 不拋例外、不區分大小寫

// 巢狀型別
Type.GetType("OuterClass+NestedClass")

// 動態調用(晚期繫結)
type.InvokeMember("MethodName", BindingFlags.InvokeMethod, null, instance, args)

取得 Type 實例的三種方式

方式語法特點適用場景
物件.GetType() obj.GetType() 需先有實例、取得執行期實際型別 已有物件、多型情境
Type.GetType() Type.GetType("FullName") 無需實例、支援字串動態指定、跨組件 設定檔驅動、外掛載入、序列化還原
typeof 運算子 typeof(MyClass) 編譯期繫結、型別安全、效能最佳 已知型別、泛型參數、屬性標記

BindingFlags 詳細說明

控制反射搜尋範圍的關鍵旗標(可組合):

BindingFlags.Public        // 公開成員
BindingFlags.NonPublic     // 非公開成員
BindingFlags.Instance      // 實例成員
BindingFlags.Static        // 靜態成員
BindingFlags.DeclaredOnly  // 僅宣告於此型別(不含繼承)
BindingFlags.FlattenHierarchy // 靜態成員包含繼承鏈

// 常用組合
var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;

實用範例:完整型別檢視器

public static void DumpTypeInfo(Type type)
{
    Console.WriteLine($"=== {type.FullName} ===");
    Console.WriteLine($"Base: {type.BaseType?.FullName ?? "null"}");
    Console.WriteLine($"Interfaces: {string.Join(", ", type.GetInterfaces().Select(i => i.Name))}");
    Console.WriteLine($"IsClass: {type.IsClass}, IsInterface: {type.IsInterface}, IsValueType: {type.IsValueType}");

    Console.WriteLine("\n--- Constructors ---");
    foreach (var ctor in type.GetConstructors())
        Console.WriteLine($"  {ctor}");

    Console.WriteLine("\n--- Methods ---");
    foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
        Console.WriteLine($"  {method.ReturnType.Name} {method.Name}({string.Join(", ", method.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"))})");

    Console.WriteLine("\n--- Properties ---");
    foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
        Console.WriteLine($"  {prop.PropertyType.Name} {prop.Name} {{ {(prop.CanRead ? "get" : "")} {(prop.CanWrite ? "set" : "")} }}");

    Console.WriteLine("\n--- Fields ---");
    foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
        Console.WriteLine($"  {field.FieldType.Name} {field.Name}");

    Console.WriteLine("\n--- Events ---");
    foreach (var evt in type.GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
        Console.WriteLine($"  {evt.EventHandlerType.Name} {evt.Name}");
}

注意事項與最佳實踐

  • 效能:反射顯著慢於直接呼叫,熱路徑請快取 Type/MethodInfo 或改用委派/Expression Trees
  • 安全性:NonPublic 存取需 ReflectionPermission,沙箱環境可能受限
  • 版本相容:依名稱字串取得成員易因重構中斷,建議搭配 `nameof()` 或編譯期驗證
  • 泛型處理:開放泛型 typeof(List<>) vs 封閉泛型 typeof(List),MakeGenericType 動態建構

精通 System.Reflection 是開發框架、序列化器、DI 容器、測試工具、程式碼產生器的基礎功力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved