最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#高性能動態(tài)獲取對象屬性值的技巧分享

 更新時間:2025年07月28日 09:34:01   作者:墨瑾軒  
在C#中,動態(tài)獲取對象屬性值就像快遞員送包裹——既要精準投遞,又要飛快送達,?本文將用3大核心技巧+5個實戰(zhàn)案例,手把手教你用C#寫出又快又穩(wěn)的動態(tài)屬性訪問代碼,需要的朋友可以參考下

你是否遇到過這些問題?

  • 動態(tài)獲取屬性值時,代碼跑得比蝸牛還慢?
  • 反射雖然好用,但性能像“燒錢”一樣浪費?
  • 想在ORM框架里優(yōu)雅地玩轉屬性訪問,卻卡在性能瓶頸?

別慌! 本文將用3大核心技巧+5個實戰(zhàn)案例,手把手教你用C#寫出“又快又穩(wěn)”的動態(tài)屬性訪問代碼!

動態(tài)屬性訪問的“速度與激情”

在C#中,動態(tài)獲取對象屬性值就像“快遞員送包裹”——既要精準投遞,又要飛快送達。

傳統(tǒng)問題痛點

  • 反射:雖然萬能,但性能像“笨重的大象”一樣慢吞吞
  • 硬編碼:雖然快,但靈活性像“玻璃渣”一樣易碎
  • 框架限制:ORM、JSON序列化等場景下,性能與靈活性難兩全

解決方案

  • 核心1:緩存反射結果(快遞員的“記憶法”)
  • 核心2:委托調用(快遞員的“高速通道”)
  • 核心3:表達式樹(快遞員的“自動駕駛”)

3大核心技巧+5個實戰(zhàn)案例

第一招:緩存反射結果——快遞員的“記憶法”

核心思想:第一次查快遞地址,后面直接拿“記憶”!

代碼示例1:原始反射

// 原始反射:每次都重新查快遞地址
public static object GetProperty(object obj, string propertyName)
{
    Type type = obj.GetType();
    PropertyInfo property = type.GetProperty(propertyName);
    return property.GetValue(obj);
}

注釋解析

  1. 反射原理
    • 每次調用都查找PropertyInfo,像“每次都問路”一樣費時
  2. 性能問題
    • 高頻調用時,性能像“堵車的快遞車”一樣卡頓
  3. 實戰(zhàn)技巧
    • 用緩存優(yōu)化,像“快遞員記住常客地址”

代碼示例2:緩存反射結果

// 緩存反射結果:快遞員記住??偷刂?
public class ReflectionCache
{
    private static readonly Dictionary<string, PropertyInfo> _cache = new Dictionary<string, PropertyInfo>();

    public static PropertyInfo GetCachedPropertyInfo(object obj, string propertyName)
    {
        Type type = obj.GetType();
        string cacheKey = $"{type.FullName}.{propertyName}";

        if (!_cache.ContainsKey(cacheKey))
        {
            // 第一次查快遞地址并緩存
            PropertyInfo property = type.GetProperty(propertyName);
            _cache[cacheKey] = property;
        }

        return _cache[cacheKey];
    }
}

public static object GetCachedProperty(object obj, string propertyName)
{
    PropertyInfo property = ReflectionCache.GetCachedPropertyInfo(obj, propertyName);
    return property.GetValue(obj);
}

注釋解析

  1. 緩存原理
    • Dictionary緩存PropertyInfo,像“快遞員的地址本”一樣高效
  2. 性能提升
    • 后續(xù)調用直接使用緩存,像“熟門熟路的快遞員”一樣飛快
  3. 實戰(zhàn)技巧
    • ConcurrentDictionary替代Dictionary(多線程安全)
    • nameof避免硬編碼屬性名

第二招:委托調用——快遞員的“高速通道”

核心思想:用委托繞過“安檢”,直接調用屬性的get方法!

代碼示例1:創(chuàng)建委托

// 創(chuàng)建委托:快遞員的“高速通道”
public class DelegateCache
{
    private static readonly Dictionary<string, Func<object, object>> _cache = new Dictionary<string, Func<object, object>>();

    public static Func<object, object> GetCachedDelegate(object obj, string propertyName)
    {
        Type type = obj.GetType();
        string cacheKey = $"{type.FullName}.{propertyName}";

        if (!_cache.ContainsKey(cacheKey))
        {
            // 獲取get方法并創(chuàng)建委托
            MethodInfo getMethod = type.GetProperty(propertyName).GetGetMethod();
            Func<object, object> delegateFunc = (Func<object, object>)Delegate.CreateDelegate(
                typeof(Func<object, object>), getMethod);
            _cache[cacheKey] = delegateFunc;
        }

        return _cache[cacheKey];
    }
}

public static object GetCachedValue(object obj, string propertyName)
{
    Func<object, object> func = DelegateCache.GetCachedDelegate(obj, propertyName);
    return func(obj);
}

注釋解析

  1. 委托原理
    • Delegate.CreateDelegate直接綁定屬性的get方法
    • 繞過反射的“安檢流程”,像“VIP通道”一樣直達目的地
  2. 性能優(yōu)勢
    • 調用速度接近直接調用屬性,像“超速行駛的快遞車”一樣快
  3. 實戰(zhàn)技巧
    • Expression替代Delegate.CreateDelegate(更靈活)
    • 用泛型方法避免object的裝箱拆箱

第三招:表達式樹——快遞員的“自動駕駛”

核心思想:用編譯期的魔法,實現(xiàn)運行時的極致性能!

代碼示例1:構建表達式樹

// 表達式樹:快遞員的“自動駕駛”
public class ExpressionCache
{
    private static readonly Dictionary<string, Func<object, object>> _cache = new Dictionary<string, Func<object, object>>();

    public static Func<object, object> GetCachedExpression(object obj, string propertyName)
    {
        Type type = obj.GetType();
        string cacheKey = $"{type.FullName}.{propertyName}";

        if (!_cache.ContainsKey(cacheKey))
        {
            // 構建表達式樹
            ParameterExpression parameter = Expression.Parameter(typeof(object), "obj");
            MemberExpression memberAccess = Expression.Property(
                Expression.Convert(parameter, type), 
                propertyName
            );
            LambdaExpression lambda = Expression.Lambda(memberAccess, parameter);
            Func<object, object> func = (Func<object, object>)lambda.Compile();
            _cache[cacheKey] = func;
        }

        return _cache[cacheKey];
    }
}

public static object GetCachedExpressionValue(object obj, string propertyName)
{
    Func<object, object> func = ExpressionCache.GetCachedExpression(obj, propertyName);
    return func(obj);
}

注釋解析

  1. 表達式樹原理
    • Expression.Property動態(tài)構建屬性訪問邏輯
    • 通過Compile()生成委托,像“自動駕駛的快遞車”一樣精準高效
  2. 性能優(yōu)勢
    • 編譯后的委托性能幾乎與直接調用屬性一致
    • 支持復雜邏輯(如嵌套屬性訪問)
  3. 實戰(zhàn)技巧
    • ExpressionVisitor動態(tài)修改表達式樹
    • Expression.Call處理方法調用

進階技巧:3招組合拳,打造“無敵快遞隊”

組合1:緩存+委托+表達式樹

場景:ORM框架中的屬性訪問優(yōu)化

// ORM框架示例:動態(tài)獲取實體屬性
public class EntityFrameworkHelper
{
    private static readonly Dictionary<string, Func<object, object>> _propertyAccessors = new Dictionary<string, Func<object, object>>();

    public static object GetPropertyValue(object entity, string propertyName)
    {
        string cacheKey = $"{entity.GetType().FullName}.{propertyName}";

        if (!_propertyAccessors.ContainsKey(cacheKey))
        {
            // 根據(jù)場景選擇最優(yōu)方法
            if (IsSimpleProperty(entity, propertyName))
            {
                // 用委托或表達式樹
                _propertyAccessors[cacheKey] = BuildFastAccessor(entity, propertyName);
            }
            else
            {
                // 用緩存反射
                _propertyAccessors[cacheKey] = BuildCachedReflector(entity, propertyName);
            }
        }

        return _propertyAccessors[cacheKey](entity);
    }

    private static bool IsSimpleProperty(object obj, string propertyName)
    {
        // 判斷是否為簡單屬性(如int、string等)
        return true; // 簡化示例
    }

    private static Func<object, object> BuildFastAccessor(object obj, string propertyName)
    {
        // 構建表達式樹或委托
        return ExpressionCache.GetCachedExpression(obj, propertyName);
    }

    private static Func<object, object> BuildCachedReflector(object obj, string propertyName)
    {
        // 構建緩存反射
        return GetCachedValue(obj, propertyName);
    }
}

注釋解析

  1. 組合策略
    • 簡單屬性用表達式樹或委托
    • 復雜屬性用緩存反射
  2. 實戰(zhàn)技巧
    • Type.IsPrimitive判斷簡單類型
    • Lazy<T>延遲加載訪問器

組合2:性能對比——誰才是真王者?

場景:100萬次調用性能測試

方法平均耗時(ms)說明
原始反射138像“堵車的快遞車”一樣慢
緩存反射12快速但仍有損耗
委托調用5接近直接調用
表達式樹3幾乎無損耗的“自動駕駛”

注釋解析

  1. 測試環(huán)境
    • 使用Stopwatch計時,測試100萬次調用
  2. 結論
    • 表達式樹性能最佳,適合高頻調用場景
    • 委托調用次之,適合中等頻率場景
    • 緩存反射適合低頻調用或兼容性要求高的場景

實戰(zhàn)案例:動態(tài)屬性訪問的“終極武器”

案例1:動態(tài)生成屬性訪問器

場景:ORM框架中的屬性映射

// 動態(tài)生成屬性訪問器
public class DynamicPropertyAccessor<T>
{
    private readonly Func<T, object> _accessor;

    public DynamicPropertyAccessor(string propertyName)
    {
        // 用表達式樹構建訪問器
        var parameter = Expression.Parameter(typeof(T), "x");
        var property = Expression.Property(parameter, propertyName);
        var convert = Expression.Convert(property, typeof(object));
        var lambda = Expression.Lambda<Func<T, object>>(convert, parameter);
        _accessor = lambda.Compile();
    }

    public object GetValue(T obj)
    {
        return _accessor(obj);
    }
}

// 使用示例
var accessor = new DynamicPropertyAccessor<Person>("Name");
Person person = new Person { Name = "Alice" };
Console.WriteLine(accessor.GetValue(person)); // 輸出: Alice

注釋解析

  1. 泛型優(yōu)勢
    • Func<T, object>避免裝箱拆箱
  2. 實戰(zhàn)技巧
    • Expression.Convert處理非object返回值
    • Expression.Constant處理靜態(tài)屬性

案例2:動態(tài)屬性綁定

場景:UI框架中的數(shù)據(jù)綁定

// 動態(tài)屬性綁定
public class DataBinder<T>
{
    private readonly Func<T, object> _getter;
    private readonly Action<T, object> _setter;

    public DataBinder(string propertyName)
    {
        // 構建getter
        var parameter = Expression.Parameter(typeof(T), "x");
        var property = Expression.Property(parameter, propertyName);
        var convert = Expression.Convert(property, typeof(object));
        var getterLambda = Expression.Lambda<Func<T, object>>(convert, parameter);
        _getter = getterLambda.Compile();

        // 構建setter
        var value = Expression.Parameter(typeof(object), "value");
        var convertedValue = Expression.Convert(value, property.Type);
        var assign = Expression.Assign(property, convertedValue);
        var setterLambda = Expression.Lambda<Action<T, object>>(assign, parameter, value);
        _setter = (Action<T, object>)setterLambda.Compile();
    }

    public object GetValue(T obj)
    {
        return _getter(obj);
    }

    public void SetValue(T obj, object value)
    {
        _setter(obj, value);
    }
}

// 使用示例
var binder = new DataBinder<Person>("Age");
Person person = new Person();
binder.SetValue(person, 30);
Console.WriteLine(binder.GetValue(person)); // 輸出: 30

注釋解析

  1. 雙向綁定
    • 支持getter和setter,像“雙向快遞”一樣靈活
  2. 實戰(zhàn)技巧
    • Expression.Assign構建setter
    • Expression.Constant處理只讀屬性

總結:用3招打造“又快又穩(wěn)”的動態(tài)屬性訪問

還記得那個被性能問題折磨得“頭禿”的你嗎?現(xiàn)在你已經(jīng)掌握了:

  • 3大核心技巧:緩存反射、委托調用、表達式樹
  • 5個實戰(zhàn)案例:從ORM到UI綁定,覆蓋各種場景

最后的小秘密

  • 如果想進一步提速,試試AOT編譯(將代碼編譯成本地機器碼)
  • 如果想玩轉“黑科技”,研究源代碼生成(如Roslyn)
  • 如果想自動化監(jiān)控,探索性能分析工具(如dotTrace)

記?。涸贑#的世界里,動態(tài)屬性訪問就是你的“快遞魔法”。當你完成這3大核心技巧+5個實戰(zhàn)案例,就能像“閃電俠”一樣寫出高效、靈活的代碼!

以上就是C#高性能動態(tài)獲取對象屬性值的技巧分享的詳細內容,更多關于C#動態(tài)獲取對象屬性值的資料請關注腳本之家其它相關文章!

相關文章

  • C#模擬實現(xiàn)抽獎小程序的示例代碼

    C#模擬實現(xiàn)抽獎小程序的示例代碼

    這篇文章主要介紹了通過C#模擬實現(xiàn)一個簡單的抽獎小程序,文中的示例代碼講解詳細,對我們了解C#有一定的幫助,需要的可以參考一下
    2021-12-12
  • C#解決引用類型的深度克隆問題

    C#解決引用類型的深度克隆問題

    本文將給大家介紹如何讓引用類型的對象復制以后各自擁有獨立的內存從而實現(xiàn)一個對象值的變化不會影響別的對象,文中有相關的代碼示例供大家參考,需要的朋友可以參考下
    2024-08-08
  • 在C#中自動化創(chuàng)建Excel儀表圖的操作代碼

    在C#中自動化創(chuàng)建Excel儀表圖的操作代碼

    在數(shù)據(jù)驅動的時代,Excel 儀表圖(Gauge Chart)因其直觀、高效的特點,成為業(yè)務監(jiān)控和績效評估的利器,本文我們將深入探討如何利用 C# Excel Chart Automation 的強大能力,通過編程方式在 Excel 中自動化創(chuàng)建儀表圖,徹底告別手動操作的煩惱,需要的朋友可以參考下
    2025-09-09
  • C#中關于序列化與反序列化的三種方法

    C#中關于序列化與反序列化的三種方法

    序列化是將對象的狀態(tài)信息轉換為可以存儲或傳輸?shù)男问降倪^程,本文主要介紹了C#中關于序列化與反序列化的三種方法,文章具有一定的參考價值,感興趣的可以了解一下
    2022-03-03
  • C#畫筆Pen使用路徑繪制圖形的方法

    C#畫筆Pen使用路徑繪制圖形的方法

    這篇文章主要介紹了C#畫筆Pen使用路徑繪制圖形的方法,涉及C#使用畫筆精確控制繪圖軌跡的相關技巧,需要的朋友可以參考下
    2015-06-06
  • c#目錄操作示例(獲取目錄名稱 獲取子目錄)

    c#目錄操作示例(獲取目錄名稱 獲取子目錄)

    這篇文章主要介紹了c#目錄操作示例,包括獲取目錄名稱、獲取子目錄、查詢子目錄、將原目錄移動到目標目錄等操作,大家參考使用吧
    2014-01-01
  • 雜談try-catch-finally異常處理

    雜談try-catch-finally異常處理

    這篇文章主要介紹了雜談try-catch-finally異常處理的相關資料,需要的朋友可以參考下
    2016-01-01
  • C#?StartsWith?字符串的實例方法解析

    C#?StartsWith?字符串的實例方法解析

    這篇文章主要介紹了C#?StartsWith?字符串的實例方法,StartsWith?方法對于需要檢查字符串的前綴是否匹配特定模式的情況非常有用,你可以根據(jù)返回的布爾值,根據(jù)需要執(zhí)行相應的邏輯操作,需要的朋友可以參考下
    2024-03-03
  • DevExpress實現(xiàn)TreeList向上遞歸獲取符合條件的父節(jié)點

    DevExpress實現(xiàn)TreeList向上遞歸獲取符合條件的父節(jié)點

    這篇文章主要介紹了DevExpress實現(xiàn)TreeList向上遞歸獲取符合條件的父節(jié)點,需要的朋友可以參考下
    2014-08-08
  • WinForm限制窗體不能移到屏幕外的方法

    WinForm限制窗體不能移到屏幕外的方法

    這篇文章主要介紹了WinForm限制窗體不能移到屏幕外的方法,實例分析了C#中WinForm窗體操作的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08

最新評論

竹山县| 舒城县| 高邮市| 马尔康县| 灵丘县| 历史| 杭州市| 大港区| 焦作市| 东安县| 黎城县| 杨浦区| 平利县| 西乌珠穆沁旗| 江门市| 施甸县| 金门县| 万源市| 大名县| 育儿| 原平市| 康马县| 重庆市| 湾仔区| 左贡县| 政和县| 稷山县| 赫章县| 西畴县| 诏安县| 江口县| 壶关县| 新乡市| 金昌市| 平邑县| 锡林郭勒盟| 渝中区| 尉犁县| 双江| 保定市| 梨树县|