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

C# 反射完整指南:核心概念、API 操作與實戰應用場景

     編輯:關於C#

反射是什麼?

Reflection (反射) 是 .NET 執行時機制,允許程式在**執行期**檢視、操作組件中的型別中繼資料:類別、結構、介面、列舉、委派、方法、屬性、事件、建構子、欄位、屬性 (Attribute) 等。甚至能**動態建立實例、呼叫方法、存取私有成員**、實作外掛架構、序列化、ORM、單元測試框架等核心基礎設施。

組件載入層級結構

AppDomain (應用程式域)
  └─ Assembly (組件) ── .dll / .exe
        └─ Module (模組)
              └─ Type (型別) ── Class / Struct / Interface / Enum / Delegate
                    ├─ ConstructorInfo (建構子)
                    ├─ MethodInfo (方法)
                    ├─ PropertyInfo (屬性)
                    ├─ FieldInfo (欄位)
                    ├─ EventInfo (事件)
                    └─ ParameterInfo (參數)

核心 API 快速查閱

類別常用靜態/實例方法用途
AssemblyLoadFrom, Load, GetTypes, GetType, CreateInstance載入組件、列舉/取得型別、建立實例
TypeGetType, GetConstructors, GetMethods, GetProperties, GetFields, GetEvents, GetInterfaces, GetCustomAttributes型別中繼資料核心入口
ActivatorCreateInstance(type), CreateInstance(type, args)動態建立實例 (支援建構子參數)
MethodInfoInvoke(obj, params), GetParameters, ReturnType動態呼叫方法
PropertyInfoGetValue/SetValue(obj), PropertyType, CanRead/CanWrite動態存取屬性
FieldInfoGetValue/SetValue(obj), FieldType, IsPublic/IsStatic動態存取欄位 (含私有)
ConstructorInfoInvoke(args), GetParameters動態呼叫建構子

實戰範例:動態載入外掛並呼叫方法


// 1. 定義外掛介面 (雙方共用組件)
public interface IPlugin
{
    string Name { get; }
    void Execute(string input);
}

// 2. 外掛實作 (獨立組件 PluginA.dll)
public class PluginA : IPlugin
{
    public string Name => "Plugin A";
    public void Execute(string input) => Console.WriteLine($"[PluginA] 處理: {input}");
}

// 3. 主程式動態載入
public class PluginLoader
{
    public IEnumerable LoadPlugins(string folderPath)
    {
        foreach (var file in Directory.GetFiles(folderPath, "*.dll"))
        {
            Assembly asm = null;
            try { asm = Assembly.LoadFrom(file); }
            catch { continue; } // 忽略非 .NET 或載入失敗

            foreach (var type in asm.GetTypes())
            {
                if (typeof(IPlugin).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
                {
                    if (Activator.CreateInstance(type) is IPlugin plugin)
                        yield return plugin;
                }
            }
        }
    }
}

// 4. 使用
var loader = new PluginLoader();
foreach (var plugin in loader.LoadPlugins(@".\Plugins"))
{
    Console.WriteLine($"載入: {plugin.Name}");
    plugin.Execute("Hello Reflection");
}

進階技巧與效能優化

技巧說明
Delegate 緩存將 `MethodInfo` 轉為 `Func<,>` / `Action<,>` 緩存,避免重複 `Invoke` 開銷 (10-100x 加速)。
表達式樹編譯用 `Expression.Lambda` 建立強型別委派,JIT 優化更好。
Source Generators (C# 9+)編譯期產生程式碼替代執行期反射 (如 JSON 序列化、gRPC、DI 容器)。
只反射 Public/需要的成員`BindingFlags.Public | BindingFlags.Instance` 縮小搜尋範圍。
避免迴圈中 GetType()型別物件不可變,提取至迴圈外。

常見應用場景

  • 外掛/模組系統:動態發現、載入實作特定介面的型別。
  • 序列化/反序列化:JSON.NET、XmlSerializer、Protobuf-net 透過反射對應屬性。
  • ORM / 實體映射:Entity Framework、Dapper 映射資料庫欄位至屬性。
  • 依賴注入容器:Autofac、Microsoft.Extensions.DI 掃描建構子、屬性注入點。
  • 單元測試框架:NUnit/xUnit 掃描 `[Test]` 屬性方法、建構測試類別實例。
  • 物件複製/映射:AutoMapper、Mapster 依反射複製屬性值。
  • 動態代理/AOP:Castle DynamicProxy 攔截方法呼叫實作日誌、快取、交易。

安全性與權限

  • 反射可繞過 `private`/`internal` 存取修飾詞 (需 `ReflectionPermission` / `MemberAccess`)。
  • .NET Core / 5+ 預設允許反射非公用成員,但受 `RuntimeFeature.IsDynamicCodeSupported` 限制 (AOT/Trimming 環境可能失效)。
  • 生產環境建議:**最小權限原則**,僅反射必要成員,避免惡意程式碼竄改內部狀態。

總結

反射是 .NET **動態能力的基石**,賦予程式「自我認知」與「自我修改」的能力。掌握 `Assembly` → `Type` → `MemberInfo` → `Invoke/SetValue` 的操作鏈,並善用委派緩存、Source Generators 等現代優化手段,能構建極具擴充性的框架與工具。但請記住:**反射威力大、責任大**——僅在真正需要動態性時使用,靜態型別安全永遠是首選。

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