Automapper嵌套映射

问题描述:

我读过嵌套的映射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的控制。

它缺少从地址到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

考虑,而不是执行以下操作:

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它会为您解释投影,您可以自定义它以按照您的方式工作。

重要的是你定义了你的导航有多深,以预防*的问题。想象一下这种可能性:

你有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! –