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

C# 集合物件屬性高效映射複製(反射 + 快取優化)

     編輯:關於C#

針對 List<T> 之間屬性複製,透過反射配合 Dictionary 快取 PropertyMapper 避免重複 GetProperties(),支援同名同型屬性單向複製(來源可讀、目標可寫)。

適用場景

  • Web Service DTO ↔ Silverlight/ViewModel 實體互轉
  • 不同命名空間但結構相似的類別映射
  • 減少序列化依賴,解耦層級

核心實作:ObjectMapper

public static class ObjectMapper {
    // 快取:Key = "SourceFullName_TargetFullName",Value = 屬性映射清單
    static readonly Dictionary<string, List<PropertyMapper>> _cache
        = new Dictionary<string, List<PropertyMapper>>();

    // 公開進入點:集合複製
    public static void CopyProperties<TSource, TTarget>(List<TSource> src, List<TTarget> dst)
        where TTarget : new() {
        if (src == null || dst == null) return;
        foreach (var s in src) {
            var t = new TTarget();
            CopyProperties(s, t);
            dst.Add(t);
        }
    }

    // 單一物件複製
    public static void CopyProperties(object src, object dst) {
        if (src == null || dst == null) return;
        var key = $"{src.GetType().FullName}_{dst.GetType().FullName}";
        if (!_cache.ContainsKey(key)) BuildMapper(src.GetType(), dst.GetType());
        foreach (var pm in _cache[key]) {
            var val = pm.Source.GetValue(src);
            pm.Target.SetValue(dst, val);
        }
    }

    // 建立映射:同名、同型、可讀/可寫
    static void BuildMapper(Type srcType, Type dstType) {
        var key = $"{srcType.FullName}_{dstType.FullName}";
        if (_cache.ContainsKey(key)) return;

        var maps = from sp in srcType.GetProperties()
                   join tp in dstType.GetProperties() on sp.Name equals tp.Name
                   where sp.CanRead && tp.CanWrite && sp.PropertyType == tp.PropertyType
                   select new PropertyMapper { Source = sp, Target = tp };

        _cache[key] = maps.ToList();
    }

    class PropertyMapper {
        public PropertyInfo Source { get; set; }
        public PropertyInfo Target { get; set; }
    }
}

單元測試驗證

[TestMethod]
public void CopyProperties_List_Test() {
    var src = Enumerable.Range(0, 10).Select(i => new SrcEntity {
        Name = "jasen", Time = DateTime.Parse("2011-5-13"), Flag = true, Option = ConflictOption.OverwriteChanges, Index = i
    }).ToList();

    var dst = new List<DstEntity>();
    ObjectMapper.CopyProperties(src, dst);

    for (int i = 0; i < 10; i++) {
        Assert.AreEqual(src[i].Name, dst[i].Name);
        Assert.AreEqual(src[i].Time, dst[i].Time);
        Assert.AreEqual(src[i].Flag, dst[i].Flag);
        Assert.AreEqual(src[i].Option, dst[i].Option);
    }
}

class SrcEntity {
    public string Name { get; set; }
    public DateTime Time { get; set; }
    public bool Flag { get; set; }
    public ConflictOption Option { get; set; }
    public int Index { get; set; }
}
class DstEntity {
    public string Name { get; set; }
    public DateTime Time { get; set; }
    public bool Flag { get; set; }
    public ConflictOption Option { get; set; }
    public int Index { get; set; }
}

效能優化重點

  1. 靜態 Dictionary 快取:Type 配對只反射一次,後續直接取用 PropertyMapper 清單
  2. 委派/Expression Tree 進階版:可進一步將 GetValue/SetValue 編譯為強型別委派,提升 10x+ 效能(本範例未實作)
  3. 巢狀集合屬性:若屬性為 IList,可遞迴呼叫 CopyProperties 處理

原始碼下載:Jasen.CopyObjectToObjectSample.rar

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