当源对象没有继承关系时,如何使用 AutoMapper 包含子对象映射?
How can I include a child object mapping using AutoMapper when the source objects have no inheritance relationship?
我有一个类似这样的对象模型:
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
派生的。
有没有一种简单的方法可以将一个映射导入另一个映射,但指定它应该从源类型的子对象映射?即“嘿,请将 source.Child 映射到此,然后 运行 常规源>此映射?”
我要在这里做一个假设,但我认为映射应该是从 TicketOrder
到 TicketOrderDto
,而不是 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));
我有一个类似这样的对象模型:
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
派生的。
有没有一种简单的方法可以将一个映射导入另一个映射,但指定它应该从源类型的子对象映射?即“嘿,请将 source.Child 映射到此,然后 运行 常规源>此映射?”
我要在这里做一个假设,但我认为映射应该是从 TicketOrder
到 TicketOrderDto
,而不是 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));