项目
版本

AutoMapper 值转换器(Value Converters)

值转换器是 类型转换器值解析器 的结合体。类型转换器是全局范围的,这意味着任何时间你从类型 Foo 映射到类型 Bar 的时候,在任何映射中都会使用该类型转换器。而值转换器则是限定在单一映射中的,它接收源对象和目标对象,并解析出一个值映射到目标成员上。此外,值转换器还可以选择性地接收源成员信息。

简化语法如下:

  • 类型转换器 = Func<TSource, TDestination, TDestination>
  • 值解析器 = Func<TSource, TDestination, TDestinationMember>
  • 成员值解析器 = Func<TSource, TDestination, TSourceMember, TDestinationMember>
  • 值转换器 = Func<TSourceMember, TDestinationMember>

要在成员级别配置值转换器,可以这样做:

public class CurrencyFormatter : IValueConverter<decimal, string>
{
    public string Convert(decimal source, ResolutionContext context)
        => source.ToString("c");
}

var configuration = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Order, OrderDto>()
        .ForMember(d => d.Amount, opt => opt.ConvertUsing(new CurrencyFormatter()));
    cfg.CreateMap<OrderLineItem, OrderLineItemDto>()
        .ForMember(d => d.Total, opt => opt.ConvertUsing(new CurrencyFormatter()));
});

如果源成员名称不匹配,你可以自定义源成员:

public class CurrencyFormatter : IValueConverter<decimal, string>
{
    public string Convert(decimal source, ResolutionContext context)
        => source.ToString("c");
}

var configuration = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Order, OrderDto>()
        .ForMember(d => d.Amount, opt => opt.ConvertUsing(new CurrencyFormatter(), src => src.OrderAmount));
    cfg.CreateMap<OrderLineItem, OrderLineItemDto>()
        .ForMember(d => d.Total, opt => opt.ConvertUsing(new CurrencyFormatter(), src => src.LITotal));
});

如果你需要服务定位器 ( 依赖注入 ) 实例化值转换器,可以指定类型而非实例:

var configuration = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Order, OrderDto>()
        .ForMember(d => d.Amount, opt => opt.ConvertUsing<CurrencyFormatter, decimal>());
    cfg.CreateMap<OrderLineItem, OrderLineItemDto>()
        .ForMember(d => d.Total, opt => opt.ConvertUsing<CurrencyFormatter, decimal>());
});

如果你在运行时不知道类型或成员名称,可以使用接受 System.Type 和基于 string 的成员的各种重载方法:

var configuration = new MapperConfiguration(cfg =>
{
    cfg.CreateMap(typeof(Order), typeof(OrderDto))
        .ForMember("Amount", opt => opt.ConvertUsing(new CurrencyFormatter(), "OrderAmount"));
    cfg.CreateMap(typeof(OrderLineItem), typeof(OrderLineItemDto))
        .ForMember("Total", opt => opt.ConvertUsing(new CurrencyFormatter(), "LITotal"));
});

值转换器仅用于内存映射执行,它们不适用于 ProjectTo 查询扩展方法 。

在本文档中