對象到對象映射-AutoMapper

概述

AutoMapper 是一個對象-對象映射器,能夠將一個對象映射到另外一個對象。app

用來解決一個看似複雜的問題,這種類型的代碼編寫起來至關枯燥乏味,編輯器

官網地址:函數

http://automapper.org/spa

官方文檔:code

https://docs.automapper.org/en/latest/對象

入門

AutoMapper支持使用靜態服務位置構造「自定義值解析器」,「自定義類型轉換器」和「值轉換器」的功能:blog

var configuration = new MapperConfiguration(cfg =>
{
    cfg.ConstructServicesUsing(ObjectFactory.GetInstance);

    cfg.CreateMap<Source, Destination>();
});

或動態服務位置,用於基於實例的容器(包括子容器/嵌套容器):作用域

var mapper = new Mapper(configuration, childContainer.GetInstance);

var dest = mapper.Map<Source, Destination>(new Source { Value = 15 });

您可使用配置文件定義配置。而後,經過在啓動時調用IServiceCollection擴展方法AddAutoMapper,使AutoMapper知道這些概要文件在哪些程序集中定義:文檔

services.AddAutoMapper(profileAssembly1, profileAssembly2 /*, ...*/);

或標記類型:字符串

services.AddAutoMapper(typeof(ProfileTypeFromAssembly1), typeof(ProfileTypeFromAssembly2) /*, ...*/);

如今,您能夠在運行時將AutoMapper注入服務/控制器中:

public class EmployeesController {
  private readonly IMapper _mapper;

  public EmployeesController(IMapper mapper) => _mapper = mapper;

  // use _mapper.Map or _mapper.ProjectTo
}

固然還有不少可擴展性,好比:

定製類型轉換器

有時,您須要徹底控制從一種類型到另外一種類型的轉換。一般,這是當一種類型看起來與另外一種類型不同時,已經存在轉換函數,而且您但願從「鬆散」類型變爲更強的類型,例如字符串的源類型到Int32的目標類型。

例如,假設咱們的源類型爲:

public class Source
{
  public string Value1 { get; set; }
  public string Value2 { get; set; }
  public string Value3 { get; set; }
}

但您想將其映射到:

public class Destination
{
  public int Value1 { get; set; }
  public DateTime Value2 { get; set; }
  public Type Value3 { get; set; }
}

若是咱們嘗試按原樣映射這兩種類型,則AutoMapper會拋出異常(在映射時和配置檢查時),由於AutoMapper不知道從字符串到int,DateTime或Type的任何映射。要爲這些類型建立映射,咱們必須提供一個自定義類型轉換器,而且咱們能夠經過三種方式:

void ConvertUsing(Func<TSource, TDestination> mappingFunction);
void ConvertUsing(ITypeConverter<TSource, TDestination> converter);
void ConvertUsing<TTypeConverter>() where TTypeConverter : ITypeConverter<TSource, TDestination>;

第一個選項就是任何帶有源並返回目的地的函數(也有多個重載)。這適用於簡單的狀況,但對於較大的狀況則顯得笨拙。在更困難的狀況下,咱們能夠建立一個自定義的ITypeConverter <TSource,TDestination>:

public interface ITypeConverter<in TSource, TDestination>
{
  TDestination Convert(TSource source, TDestination destination, ResolutionContext context);
}

並向AutoMapper提供一個自定義類型轉換器的實例,或者爲類型提供AutoMapper將在運行時實例化的類型。咱們上面的源/目標類型的映射配置將變爲:

public void Example()
{
    var configuration = new MapperConfiguration(cfg => {
      cfg.CreateMap<string, int>().ConvertUsing(s => Convert.ToInt32(s));
      cfg.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter());
      cfg.CreateMap<string, Type>().ConvertUsing<TypeTypeConverter>();
      cfg.CreateMap<Source, Destination>();
    });
    configuration.AssertConfigurationIsValid();

    var source = new Source
    {
        Value1 = "5",
        Value2 = "01/01/2000",
        Value3 = "AutoMapperSamples.GlobalTypeConverters.GlobalTypeConverters+Destination"
    };

    Destination result = mapper.Map<Source, Destination>(source);
    result.Value3.ShouldEqual(typeof(Destination));
}

public class DateTimeTypeConverter : ITypeConverter<string, DateTime>
{
    public DateTime Convert(string source, DateTime destination, ResolutionContext context)
    {
        return System.Convert.ToDateTime(source);
    }
}

public class TypeTypeConverter : ITypeConverter<string, Type>
{
    public Type Convert(string source, Type destination, ResolutionContext context)
    {
          return Assembly.GetExecutingAssembly().GetType(source);
    }
}

在第一個映射中,從字符串到Int32,咱們僅使用內置的Convert.ToInt32函數(做爲方法組提供)。接下來的兩個使用自定義ITypeConverter實現。

自定義類型轉換器的真正強大之處在於,只要AutoMapper在任何映射類型上找到源/目標對,它們就可使用。咱們能夠構建一組自定義類型轉換器,並在其上使用其餘映射配置,而無需任何其餘配置。在上面的示例中,咱們沒必要再次指定string / int轉換。因爲必須在類型成員級別配置自定義值解析器,所以自定義類型轉換器的做用域是全局的。

固然還有不少功能須要去實際項目中實現。

相關文章
相關標籤/搜索