我正在尝试将嵌套对象放入扁平化的DTO中。我无法控制DTO或业务对象的名称,因此不幸的是,重命名/重组这些对象是不可能的。
这是我的情况的一个示例:
//Domain Objects
public class Order {
public decimal Total { get; set; }
public Customer Customer { get; set; }
}
public class Customer {
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address {
public string Street { get; set; }
public string City { get; set; }
}
//Dtos
public class OrderCustomerDTO {
public decimal Total { get; set; }
public string CustomerName { get; set; }
public string CustomerStreet { get; set; }
public string CustomerCity { get; set; }
}
//Mapping profile
public class MapperProfile : AutoMapper.Profile {
public MapperProfile() {
CreateMap<Order, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.Total, opt => opt.MapFrom(src => src.Total));
CreateMap<Customer, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Name));
CreateMap<Address, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.CustomerStreet, opt => opt.MapFrom(src => src.Street))
.ForMember(dst => dst.CustomerCity, opt => opt.MapFrom(src => src.City));
}
}
//Perform mapping
public void MapOrder(IEnumerable<Order> input) {
var config = new MapperConfiguration(cfg => {
cfg.AddProfile<MapperProfile>();
});
var mapper = config.CreateMapper();
var mapped = mapper.Map<IEnumerable<OrderCustomerDTO>>(input);
}
其结果是仅填充了OrderCustomerDTO.Total,其余的保留为空值。
我在想链接地图之类的事情,因此前一张地图链接到下一张地图,依此类推,但这会导致异常:
// Invalid map
public class MapperProfile : AutoMapper.Profile {
public MapperProfile() {
CreateMap<Order, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.Total, opt => opt.MapFrom(src => src.Total))
.ForMember(dst => dst, opt => opt.MapFrom(src => src.Customer));//Load nested type
CreateMap<Customer, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Name))
.ForMember(dst => dst, opt => opt.MapFrom(src => src.Address)); //Load nested type
CreateMap<Address, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.CustomerStreet, opt => opt.MapFrom(src => src.Street))
.ForMember(dst => dst.CustomerCity, opt => opt.MapFrom(src => src.City));
}
}
这将导致抛出异常,例如:
类型为'AutoMapper.AutoMapperConfigurationException的异常'发生在AutoMapper.dll中,但未在附加用户代码中处理信息:仅支持成员的自定义配置类型上的顶级个人成员。
很明显,我缺少有关这些嵌套映射的内容。一种解决方案(丑陋的解决方案)是将所有内容放到一张地图中,但这意味着我将拥有类似的东西:
// Ugly map
public class MapperProfile : AutoMapper.Profile {
public MapperProfile() {
CreateMap<Order, OrderCustomerDTO>(MemberList.None)
.ForMember(dst => dst.Total, opt => opt.MapFrom(src => src.Total))
.ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
.ForMember(dst => dst.CustomerStreet, opt => opt.MapFrom(src => src.Customer.Address.Street))
.ForMember(dst => dst.CustomerCity, opt => opt.MapFrom(src => src.Customer.Address.City));
}
}
很明显,这种方法不会花费很多时间,而且完全不可维护。
如何将每个嵌套对象的自动映射器映射分离到它自己的映射中,并且仍然在嵌套对象和顶部对象之间保持链接?
已找到解决方案。使用.IncludeMemers()可以解决问题,然后为包含的每种成员类型定义一个Map。我不知道它是从哪个版本实施的,但是我可以确认它适用于AM 9