2015-05-05 113 views
5

我知道有各種類似問題的問題,但據我所知(並測試),所提供的解決方案似乎都不適合,所以在這裏。使用自動映射器去規範化對象層次結構

我想知道是否可以扁平化/去規範化對象層次結構,以便使用AutoMapper將具有嵌套屬性列表的實例映射到某個目標類型的列表。

我有一個源類,看起來像

來源:

public class DistributionInformation 
{ 
    public string Streetname; 
    public RouteInformation[] Routes; 
} 

public class RouteInformation 
{ 
    public int RouteNumber; 
    public string RouteDescription; 
} 

目的地:

public class DenormDistributionInfo 
{ 
    public string Streetname; 
    public int RouteNumber; 
    public string RouteDescription; 
} 

所以我想兩個源映射到去歸一化的目的地列表DenormDistributionInfo。

即:

IEnumerable<DenormDistributionInfo> result = Mapper.Map(distributionInformationInstance); 

這有可能/可行的使用AutoMapper,或者我應該讓步,denormalise爲 「手動」?

+0

國際海事組織,使用Automapper超出非常簡單的情況下映射類型具有相同的屬性彼此是濫用Automapper。誘惑變成隱藏映射中的各種應用程序邏輯,在這一點上,你創建了比傳統方法更難理解的系統。 (披露:我不喜歡Automapper ... [朋友不讓朋友使用Automapper]) – spender

回答

4

最主要的是你想避免在查找源中隱含的數據「查找」數據。 「神奇」映射導致嚴重的維護問題。

但從概念上講,這種映射非常簡單。唯一複雜的因素是您需要兩個源對象(包括DistributionInformationRouteInformation)才能構建您的目標對象。如果你遵循思想的那班火車,我們可以創建一個非魔法地圖,清楚地保持我們的意圖 - 在這裏就是我會做: -

// We need both source objects in order to perform our map 
Mapper.CreateMap<Tuple<DistributionInformation, RouteInformation>, DenormDistributionInfo>() 
     .ForMember(d => d.Streetname, o => o.MapFrom(s => s.Item1.Streetname)) 
     .ForMember(d => d.RouteDescription, o => o.MapFrom(s => s.Item2.RouteDescription)) 
     .ForMember(d => d.RouteNumber, o => o.MapFrom(s => s.Item2.RouteNumber)); 

// We can use ConstructUsing to pass both our source objects to our map 
Mapper.CreateMap<DistributionInformation, IEnumerable<DenormDistributionInfo>>() 
     .ConstructUsing(
      x => x.Routes 
       .Select(y => Mapper.Map<DenormDistributionInfo>(Tuple.Create(x, y))) 
       .ToList()); 

並調用它: -

var flattened = Mapper.Map<IEnumerable<DenormDistributionInfo>>(source); 

如果你喜歡創建一個DTO來保存兩個源對象,你可以避免一點Tuple恐怖。如果您的真實代碼比您在問題中提供的示例稍微複雜一點,我特別強烈建議您這樣做。

無論是否使用AutoMapper執行此映射都比或多或少要複雜,不過手工由您決定。在這種情況下,我不認爲我會打擾,但在一個更復雜的情況下,經常重複我可能會考慮它。

+0

好吧,明白了。看起來像我的情況,我不妨手動映射它,無論如何,大會的例外數量意味着它是麻煩的,無論如何。 感謝您的信息。 –

0

我挖進去一點,而我選擇來解決映射問題「手動」 還有另一種方式(除了張貼伊恩答案。它不覺得相當哈克雖然。

的想法是使用一個類型轉換和映射了兩次

public class DistributionInfoConverter : ITypeConverter<DistributionInformation, IEnumerable<DenormDistributionInfo>> 
    { 
     public IEnumerable<DenormDistributionInfo> Convert(ResolutionContext context) 
     { 
      var result = new List<DenormDistributionInfo>(); 
      var source = (DistributionInformation)context.SourceValue; 

      foreach (var routeDetail in source.Routes) 
      { 
       var model = new DenormDistributionInfo(); 
       Mapper.Map(routeDetail, model); 
       Mapper.Map(source, model); 
       result.Add(model); 
      } 

      return result; 
     } 
    } 

    Mapper.CreateMap<RouteInformation, DenormDistributionInfo>(); 
    Mapper.CreateMap<DistributionInformation, DenormDistributionInfo>() 
    Mapper.CreateMap<DistributionInformation, IEnumerable<DenormDistributionInfo>>().ConvertUsing<DistributionInfoConverter>(); 

唯一的問題是,DistributionInformation集合,你必須循環/選擇每個項目和地圖,而不是讓automapper弄清楚如何將集合映射到像你一樣會收藏

相關問題