2017-04-04 172 views
2

如何讓AutoMapper將缺少的未映射屬性映射到目標對象內的字典? (像序列化過程中ExtensionDataAutoMapper將未映射的屬性映射到Dictionary/ExtensionData

例子:

class Source 
{ 
    public int A {get;set;} 
    public int B {get;set;} 
    public int C {get;set;} 
} 

class Destination 
{ 
    public int A {get;set;} 
    public Dictionary<string, object> D {get;set;} 
} 

Source s = new Source { A = 1, B = 2, C = 3 }; 
Destination d = ... // Mapping code 

現在我想以下結果:

d.A ==> 1 
d.D ==> {{ "B", 2 }, { "C", 3 }} 

*編輯*

最後,我要尋找一個解決方案沒有反射。含義:在設置/配置/初始化過程中允許反射,但在映射本身期間,我不希望由反射引起任何延遲。

*編輯*

我要尋找一個通用的解決方案,就像序列化。

+0

我不相信有一個內置的功能,要做到這一點,但是你可以創建一個使用反射來比較源自定義解析和目標物業並從那裏去。 –

+0

我已經與自定義解析器搏鬥......但這是一個痛苦。我無法想象我是第一個進入這個領域的人,因爲序列化程序具有此功能(它也將數據從一個「對象」映射到另一個)。 –

回答

4

對於您的問題有很多可能的解決方案。 我已經爲你的財產創建自定義的值解析器和它完美的作品:

public class CustomResolver : IValueResolver<Source, Destination, Dictionary<string, object>> 
{ 
    public Dictionary<string, object> Resolve(Source source, Destination destination, Dictionary<string, object> destMember, ResolutionContext context) 
    { 
     destMember = new Dictionary<string, object>(); 

     var flags = BindingFlags.Public | BindingFlags.Instance; 
     var sourceProperties = typeof(Source).GetProperties(flags); 

     foreach (var property in sourceProperties) 
     { 
      if (typeof(Destination).GetProperty(property.Name, flags) == null) 
      { 
       destMember.Add(property.Name, property.GetValue(source)); 
      } 
     } 

     return destMember; 
    } 
} 

如何使用它?

static void Main(string[] args) 
{ 
    Mapper.Initialize(cfg => { 
     cfg.CreateMap<Source, Destination>() 
      .ForMember(dest => dest.D, opt => opt.ResolveUsing<CustomResolver>()); 
    }); 

    var source = new Source { A = 1, B = 2, C = 3 }; 

    var result = Mapper.Map<Source, Destination>(source); 
} 

public class Source 
{ 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; set; } 
} 

public class Destination 
{ 
    public int A { get; set; } 
    public Dictionary<string, object> D { get; set; } 
} 
+0

不錯的解決方案。我選擇AutoMapper來防止使用反射讀取/寫入數據,因爲它很慢。 AutoMapper優化了這個過程。我希望有一個解決方案,最終,我有一個完全優化的映射過程,不會有明顯的延遲。 Anwyay ... +1給你。 –

+0

我編輯了我的問題,所以你的回答不再符合標準。但是,對我來說,這是一個非常好的開始。 –

+0

AutoMapper正在使用Reflection。 https://msdn.microsoft.com/en-us/library/system.reflection.emit(v=vs.110).aspx 我不確定是否有可能檢測未映射的屬性沒有反射。 –

2

我喜歡Pawel的解決方案,因爲它更通用。 如果你想要的東西簡單,但不通用的,你可以初始化這樣的映射:

Mapper.Initialize(cfg => { 
          cfg.CreateMap<Source, Destination>() 
           .ForMember(dest => dest.D, 
             opt => opt.MapFrom(r => new Dictionary<string,object>(){{ "B", r.B},{ "C", r.C}})); 
    }); 
+0

Thanx。是的,我正在尋找一個通用的解決方案。仍+1。 –