当源对象没有继承关系时,我如何使用AutoMapper包含子对象映射?



我有一个像这样的对象模型:

public class Concert {
public Band Band { get; set; }
public ConcertVenue Venue { get; set; }
}
public class TicketOrder { 
public Concert Concert { get; set; }
public string CustomerName { get; set; }
}
// DTOs for email and web views:
public class ConcertDto {
public string Artist { get; set; }
public string Venue { get; set; }
}
public class TicketOrderDto : ConcertDto {
public string CustomerName { get; set; }
}

我正在使用AutoMapper将域对象映射到dto。这里的dto具有域模型中不存在的继承关系(因为当我发送关于票券订单的电子邮件时,我希望包含有关音乐会的所有信息)

我有一个这样定义的映射:

config.CreateMap<Concert, ConcertDto>()
.ForMember(dto => dto.Artist, opt => opt.MapFrom(concert => concert.Band.Name))
.ForMember(dto => dto.Venue, opt => opt.MapFrom(concert => concert.GetVenueSummary());
config.CreateMap<TicketOrder, ConcertDto>()
.ForMember(dto => dto.Artist, opt => opt.MapFrom(concert => concert.Band.Name))
.ForMember(dto => dto.Venue, opt => opt.MapFrom(concert => concert.GetVenueSummary())
.ForMember(dto => dto.CustomerName, optn.MapFrom(order => order.Customer.FullName))
;

在这些映射中有一些重复,我想要做的是在映射TicketOrderDto时重用Concert > ConcertViewData映射:

cfg.CreateMap<TicketOrder, TicketOrderDto>()
// This is what I *want* but isn't valid AutoMapper syntax:
.IncludeMembers(dto => dto, order => order.Concert)
.ForMember(dto => dto.CustomerName, optn.MapFrom(order => order.Customer.FullName));

,但是使用

就失败了
System.ArgumentOutOfRangeException: Only member accesses are allowed. 
dto => dto (Parameter 'memberExpressions')
at AutoMapper.ExpressionExtensions.EnsureMemberPath(LambdaExpression exp, String name)

调用.IncludeBase<>不起作用,因为ConcertOrder不是由Concert派生的。

是否有一种简单的方法可以将一个映射导入到另一个映射,但指定它应该从源类型的子对象映射?即"嘿,请映射来源"。子进程放到这上面,然后运行常规源>这种映射?">

我要在这里做一个假设,但我相信映射应该是从TicketOrderTicketOrderDto,而不是ConcertDto(不包含CustomerName属性),因为给定的模型不匹配给定的映射配置。

在这种情况下,您应该能够在票据映射器配置上使用.AfterMap()来从Concert映射到ConcertDto

cfg.CreateMap<TicketOrder, TicketOrderDto>()            
.ForMember(d => d.CustomerName, o => o.MapFrom(s => s.Order.Customer.Name))
.AfterMap((s, d, context) => context.Mapper.Map(s.Concert, d));