项目
版本

AutoMapper 反向映射与展开

提示

6.1.0 版本开始,AutoMapper 现在支持更丰富的逆向映射支持。考虑到我们的实体如下:

public class Order {
  public decimal Total { get; set; }
  public Customer Customer { get; set; }
}

public class Customer {
  public string Name { get; set; }
}

我们可以将其扁平化为一个 DTO(数据传输对象):

public class OrderDto {
  public decimal Total { get; set; }
  public string CustomerName { get; set; }
}

我们可以在这两个方向上进行映射,包括展开操作(unflattening):

var configuration = new MapperConfiguration(cfg => {
  cfg.CreateMap<Order, OrderDto>()
     .ReverseMap();
});

通过调用 ReverseMapAutoMapper 会创建一个包含展开操作的逆向映射配置:

var customer = new Customer {
  Name = "Bob"
};

var order = new Order {
  Customer = customer,
  Total = 15.8m
};

var orderDto = mapper.Map<Order, OrderDto>(order);

orderDto.CustomerName = "Joe";

mapper.Map(orderDto, order);

order.Customer.Name.ShouldEqual("Joe");

展开操作仅在 ReverseMap 中配置。如果你需要展开功能,你必须先配置 EntityDto,然后调用 ReverseMap 来创建从 DtoEntity 的展开类型映射配置。

自定义逆向映射

AutoMapper 会根据原始的扁平化自动逆向映射 “Customer.Name” 自 “CustomerName”。如果你使用了 MapFromAutoMapper 会尝试逆向这个映射:

cfg.CreateMap<Order, OrderDto>()
  .ForMember(d => d.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
  .ReverseMap();

只要 MapFrom 路径是成员访问器,AutoMapper 就会从相同的路径展开( CustomerName => Customer.Name )。

如果你需要自定义这一点,对于逆向映射,你可以使用 ForPath

cfg.CreateMap<Order, OrderDto>()
  .ForMember(d => d.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
  .ReverseMap()
  .ForPath(s => s.Customer.Name, opt => opt.MapFrom(src => src.CustomerName));

对于大多数情况,你不需要这样做,因为原始的 MapFrom 会被自动逆向处理。当获取和设置值的路径不同时,使用 ForPath

如果你不希望有展开行为,你可以移除对 ReverseMap 的调用并创建两个独立的映射。或者,你可以使用 Ignore

cfg.CreateMap<Order, OrderDto>()
  .ForMember(d => d.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
  .ReverseMap()
  .ForPath(s => s.Customer.Name, opt => opt.Ignore());

IncludeMembers

ReverseMap 也与 IncludeMembers 和类似配置集成,

ForMember(destination => destination.IncludedMember, member => member.MapFrom(source => source))
在本文档中