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

CLR 反射深度解析:從類型檢查到動態序列化的高效能實踐

     編輯:關於.NET

.NET 反射 (System.Reflection) 讓程式在執行時檢查、操作未知類型,打破靜態編譯的限制。本文從基礎類別對應、檢查與調用、動態平均值計算實例,延伸至序列化場景的效能優化:結合 CodeDom 動態產生強型別協助類,將反射開銷從「每實例」降為「每類型一次」。

反射核心類別對應表

運行時概念System.Reflection 類別
組件Assembly
模組Module
類型Type
方法MethodInfo
建構函式ConstructorInfo
屬性PropertyInfo
欄位FieldInfo
事件EventInfo

所有成員資訊類別繼承自 MemberInfo,方法與建構函式共同繼承 MethodBase。

基礎檢查:列舉類型成員

Type t = myObject.GetType();
foreach (MethodInfo m in t.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public))
    Console.WriteLine(m.Name); // 僅列出該類別宣告的公用實例方法

BindingFlags 組合精確控制搜尋範圍:Instance/Static、Public/NonPublic、DeclaredOnly (排除繼承)、FlattenHierarchy。

動態調用:MethodInfo.Invoke

Type t = typeof(MyClass);
MethodInfo method = t.GetMethod("MyMethod2");
object[] args = { 42 };
method.Invoke(instance, args); // 等同 instance.MyMethod2(42)

關鍵特性:MethodInfo 可**脫離原始實例**綁定至**相同類型**的另一實例調用,實現「方法與實例分離」的後期繫結。

實戰範例:通用平均值計算器

public static int ComputeAverage(IEnumerable<object> objs, string methodName) {
    MethodInfo method = null;
    Type knownType = null;
    int sum = 0, count = 0;
    
    foreach (var obj in objs) {
        if (method == null) {
            knownType = obj.GetType();
            method = knownType.GetMethod(methodName);
        }
        // 關鍵限制:MethodInfo 僅能用於 knownType 或其衍生類別實例
        sum += (int)method.Invoke(obj, null);
        count++;
    }
    return count == 0 ? 0 : sum / count;
}

陷阱:若集合包含實作同名方法但**無共同基類**的類型 (如 EnemyOfIntReturner),Invoke 會拋出 TargetException。解決:快取每個具體類型的 MethodInfo,或捕獲例外後重新取得。

序列化效能優化:反射 + CodeDom

單純反射序列化每個實例都需完整類型分析,開銷大。優化策略:

  1. 分析階段:Type.GetProperties() 取得結構描述
  2. 代碼生成階段:使用 CodeDom 產生針對該類型的強型別 SerializerHelper 類別,直接存取屬性 (如 obj.Name)
  3. 編譯階段:CodeDomProvider.CompileAssemblyFromSource 產生記憶體組件
  4. 執行階段:實例化 Helper,呼叫強型別方法序列化實例

SimpleSerializer 架構

public class SimpleSerializer {
    private readonly object _helperInstance; // 動態生成的 Helper 實例
    private readonly MethodInfo _serializeMethod;
    
    public SimpleSerializer(Type dataType) {
        // 1. 反射分析 dataType 結構
        // 2. CodeDom 生成 Helper 類別原始碼
        // 3. 編譯組件、建立實例、取得序列化方法
    }
    
    public void Serialize(object input, SimpleDataWriter writer) {
        _serializeMethod.Invoke(_helperInstance, new[] { input, writer });
    }
}

後續同類型實例直接呼叫強型別 Helper,**零反射開銷**。

適用場景與取捨

  • 適用:外掛架構、通用序列化/對應框架、動態 Proxy、Scripting 整合
  • 不適用:效能極度敏感的熱路徑 (優先考慮原始碼生成器/Source Generator)、簡單已知類型操作
  • 替代方案:XmlSerializer (內建優化)、System.Text.Json (高效能)、Expression Tree (較 CodeDom 輕量)、Roslyn Source Generator (編譯時產生)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved