2011-10-24 362 views
8

我讀過嵌套的映射wiki頁面,但它似乎不喜歡多層次的嵌套。我已經創建了下面的地圖並定義了類。Automapper嵌套映射

AutoMapper.Mapper.CreateMap<Address, AddressDTO>(); 
AutoMapper.Mapper.CreateMap<MatchCompanyRequest, MatchCompanyRequestDTO>(); 

public class MatchCompanyRequest 
{ 
    Address Address {get;set;} 
} 

public class MatchCompanyRequestDTO 
{ 
    public CompanyInformationDTO {get;set;} 
} 

public class CompanyInformationDTO {get;set;} 
{ 
    public string CompanyName {get;set;} 
    public AddressDTO Address {get;set;} 
} 

但下面的代碼...

// works 
matchCompanyRequestDTO.companyInformationDTO.Address = 
    AutoMapper.Mapper.Map<Address, AddressDTO>(matchCompanyRequest.Address); 

// fails 
matchCompanyRequestDTO = 
    AutoMapper.Mapper 
     .Map<MatchCompanyRequest, MatchCompanyRequestDTO>(matchCompanyRequest); 

這是否深度嵌套的工作,我有它配置不當?還是這種嵌套尚未支持?

- 編輯

任何有興趣,我不是在DTO的控制。

回答

6

它缺少從地址到CompanyInformationDTO的映射,因爲這些對象位於相同的嵌套級別。

該地圖爲MatchCompanyRequest - >MatchCompanyRequestDTO創建,但是無法確定它是否可以將Address映射到CompanyInformationDTO

所以你MatchCompanyRequestDTO其實可以有相同的聲明爲您CompanyInformationDTO

public class MatchCompanyRequestDTO 
{ 
    public string CompanyName {get;set;} 
    public AddressDTO Address {get;set;} 
} 

這當然只是如果你想使用自動映射影響到你。您仍然可以手動配置您的地圖,但它似乎像的DTO應改用固定的,我們想試試:

public class CustomResolver : ValueResolver<Address, CompanyInformationDTO> 
{ 
    protected override CompanyInformationDTO ResolveCore(Address source) 
    { 
     return new CompanyInformationDTO() { Address = Mapper.Map<Address, AddressDTO>(source) }; 
    } 
} 
// ... 

AutoMapper.Mapper.CreateMap<MatchCompanyRequest, MatchCompanyRequestDTO>() 
    .ForMember(dest => dest.companyInformationDTO, opt => opt.ResolveUsing<CustomResolver>().FromMember(src => src.Address)); // here we are telling to use our custom resolver that converts Address into CompanyInformationDTO 
+0

怎麼會是這樣的,如果你不使用靜態配置'Mapper'實例? – dougajmcdonald

+0

然後,您只需使用您的實例而不是'AutoMapper.Mapper'?我真的不知道 - 自從我使用AutoMapper以來已經有好幾年了...... – Bartosz

+0

是的,現在最好的做法是創建一個配置文件並將其饋送到配置中,以便您可以直接使用而不使用靜態實例。我很好奇,因爲我認爲這是一種常見的解決方案,並想知道它如何適合當前的最佳實踐。 – dougajmcdonald

0

考慮,而不是執行以下操作:

public class MatchCompanyRequest 
{ 
    Address Address {get;set;} 
} 

public class MatchCompanyRequestDTO 
{ 
    public string Name {get;set;} 
    public AddressDTO Address {get;set;} 
} 

public class AddressDTO 
{ 
    .... 
} 

你的DTO對象需要具有相同結構作爲默認映射約定在AutoMapper中工作的域對象。

看看這個:https://github.com/AutoMapper/AutoMapper/wiki/Projection它會爲您解釋投影,您可以自定義它以按照您的方式工作。

4

重要的是你定義了你的導航有多深,以預防stackoverflow的問題。想象一下這種可能性:

你有2個實體用戶通知在N×N的模式(而 你DTO的對象來表示),當用戶自動映射 沒有設置MAXDEPTH在你映射器表達,「休斯頓我們有一個 問題」:)。

下面的代碼顯示了一個workarround來解決所有Mappers的問題。如果你想可以定義到每個映射器。Like this Question

解決方案1(全局定義)

public class AutoMapperConfig 
{ 
    public static void RegisterMappings() 
    { 
     Mapper.Initialize(mapperConfiguration => 
     { 
      mapperConfiguration.AddProfile<DomainModelToYourDTOsMappingProfile>(); 
      mapperConfiguration.AddProfile<YourDTOsToDomainModelMappingProfile>(); 
      mapperConfiguration.AllowNullCollections = true; 
      mapperConfiguration.ForAllMaps 
      (
       (mapType, mapperExpression) => 
       { 
        mapperExpression.MaxDepth(1); 
       }); 
      }); 
     } 
    } 

解決方案2(對於每個映射)

public class AutoMapperConfig 
{ 
    public static void RegisterMappings() 
    { 
     Mapper.CreateMap<User, DTOsModel>() 
       .MaxDepth(1); 
    } 
} 
+1

這不是OP的正確答案,但它是非常好的信息。謝謝! – Mathter

+0

謝謝@Mathter! –