人本善良

导航

09.AutoMapper 之自定义类型转换器(Custom Type Converters)

https://www.jianshu.com/p/47054d92db2a

自定义类型转换器(Custom Type Converters)

有时需要完全控制一种类型到另一种类型的转换。这一般发生在两种类型不同,已经存在转换函数,并且希望从弱类型转变为强类型,如源类型的字符串到目标类型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不知道从stringintDateTimeType的该如何映射。 要为这些类型创建映射,我们必须提供自定义类型转换器,我们有以下三种方法:

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

第一种方法是写一个委托来指定如何转换源类型到目标类型。如

cfg.CreateMap<string,int>().ConvertUsing(s=>Convert.ToInt32(s));

这种方法只能处理简单类型的情况,针对复合类型的情况我们需要创建自定义的ITypeConverter<TSource, TDestination>转换器:

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

AutoMapper提供自定义类型转换器的实例,或者只提供类型,AutoMapper将在运行时实例化。然后,上面的源/目标类型的映射配置变为:

[Test]
public void Example()
{
    Mapper.Initialize(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>();
    });
    Mapper.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);
    }
}

在第一个映射中,从string到Int32,我们只使用内置的Convert.ToInt32函数。
接下来的两个映射使用了自定义ITypeConverter实现。

自定义类型转换器的真正强大的地方在于,AutoMapper可以在任何源/目标类型上使用它们。我们可以在使用其他映射配置上方构建一组自定义类型转换器,而无需任何额外配置。在上面的例子中,我们永远不需要再次指定string/int 转换。如果必须在类型成员级别配置自定义值解析器,则自定义类型转换器的范围是全局的。

系统类型转换器

.NETFramework 通过TypeConverter类支持类型转换器的概念。AutoMapper 在配置检查和映射时支持这些类型的类型转换器,而且不需要手动配置。AutoMappe通过使用TypeDescriptor.GetConverter方法确定源/目标类型是否可映射。

posted on 2019-06-20 17:09  简简单单2018  阅读(795)  评论(0编辑  收藏  举报