• AutoMapper(三)


    返回总目录


    自定义类型转换

    有时,需要完全控制一个类型到另一个类型的转换。一个类型一点都不像另一个类型,而且转换函数已经存在了,在这种情况下,你想要从一个“宽松”的类型转换成一个更强壮的类型,例如一个string的源类型到一个int32的目标类型。

    这里有两个类Source和Destination,要把前者映射到后者,代码如下:

    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不清楚从string到int,Datetime或Type的映射,如果要尝试映射的话,AutoMapper就会抛出异常(在映射时和配置检查时)”。为了创建 这些类型的映射,我们必须提供自定义的类型转换器,我们有三种方法这样做:

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

    但是,我先不实现自定义的类型转换器试一下:

    namespace ThirdAutoMapper
    {
        class Program
        {
            static void Main(string[] args)
            {
                Mapper.CreateMap<Source, Destination>();
                var source = new Source
                {
                    Value1 = "5",
                    Value2 = "05/11/2015",
                    Value3 = "ThirdAutoMapper.Source"
                };
    
                var destination = Mapper.Map<Destination>(source);
                Console.WriteLine("destination.Value1={0}", destination.Value1);
                Console.WriteLine("destination.Value2={0}", destination.Value2);
                Console.Read();
            }
        }
    }

    出现如下错误,但从错误看来,只有从string到Type类型映射时,出现了错误,其他两种类型呢?

    image

    现在我们将源类型和目标类型的第三个属性Value3注释掉,同时注释掉参与映射前的源类型对象的Value3属性,再来试一下。

    image

    果然,发现映射成功。也就说说最新版的AutoMapper默认可以将string类型映射为int和DateTime类型了。但是string还是没办法映射为Type类型。

    对于以上AutoMapper的API给出的三种转换方法,第一个选择只是输入一个源返回一个目标的函数,这对于简单场合是有效的,但是对于更大的案例会变得难以处理。在更复杂的情况下,我们可以一个自定义的类型转换器,通过实现ITypeConverter<TSource, TDestination>接口创建:

    第一种方法:

    public class CustomTypeConverter : ITypeConverter<Source, Destination>
    {
    
        public Destination Convert(ResolutionContext context)
        {
            Source src = context.SourceValue as Source;
            var dest = new Destination
            {
                Value1 = System.Convert.ToInt32(src.Value1),
                Value2 = System.Convert.ToDateTime(src.Value2),
                Value3 = context.SourceType
            };
            return dest;
        }
    }

    然后给AutoMapper提供一个自定义类型的转换器或者AutoMapper在运行时能实例化的简化类型。对于上面的源/目标类型的映射配置就得以实现了:

    修改Main方法中的代码为:

    static void Main(string[] args)
    {
    
        Mapper.CreateMap<Source, Destination>().ConvertUsing<CustomTypeConverter>();
        var source = new Source
        {
            Value1 = "5",
            Value2 = "05/11/2015",
            Value3 = typeof(Source).ToString()
        };
    
        var destination = Mapper.Map<Destination>(source);
        Console.WriteLine("destination.Value1={0}", destination.Value1);
        Console.WriteLine("destination.Value2={0}", destination.Value2);
        Console.WriteLine(destination.Value3.ToString()==source.Value3);
        Console.WriteLine(destination.Value3);
        Console.Read();
    }

    测试结果如下,映射成功!

    image

    第二种方法:

    每个类型分别实现ITypeConverter接口:

    public class DateTimeTypeConverter:ITypeConverter<string,DateTime>
    {
    
        public DateTime Convert(ResolutionContext context)
        {
            return System.Convert.ToDateTime(context.SourceValue);
        }
    }
    
    public class TypeTypeConverter : ITypeConverter<string, Type>
    {
    
        public Type Convert(ResolutionContext context)
        {
            return context.SourceValue == typeof(Source).ToString() ? typeof(Source) : typeof(Destination);
        }
    }
    static void Main(string[] args)
    {
        //我看网上很多这种写法,包括官方文档,但是我这样写编译错误,可能是现在的AutoMapper不支持了吧
       // Mapper.CreateMap<string, int>().ConvertUsing( Convert.ToInt32);
    
        Mapper.CreateMap<string, int>().ConvertUsing((context, intNum) => Convert.ToInt32(context.SourceValue));
        Mapper.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter().Convert);
        Mapper.CreateMap<string, Type>().ConvertUsing<TypeTypeConverter>();
    
        Mapper.CreateMap<Source, Destination>();
        //Mapper.CreateMap<Source, Destination>().ConvertUsing<CustomTypeConverter>();
        var source = new Source
        {
            Value1 = "5",
            Value2 = "05/11/2015",
            Value3 = typeof(Source).ToString()
        };
    
        var destination = Mapper.Map<Destination>(source);
        Console.WriteLine("destination.Value1={0}", destination.Value1);
        Console.WriteLine("destination.Value2={0}", destination.Value2);
        Console.WriteLine(destination.Value3.ToString()==source.Value3);
        Console.WriteLine(destination.Value3);
        Console.Read();
    }

    测试结果,同样完美通过。

    image

  • 相关阅读:
    Android中Scrollview、ViewPager冲突问题汇总(已解决)
    Android 关于ZXing的使用
    startActivityForResult用法详解
    SVN的使用(服务端与客户端)
    Genymotion安装常见问题
    Android Viewpager实现图片轮播(仿优酷效果)
    Android Shape 详解
    Android apktool反编译资源文件为空解决办法(测试天猫、淘宝等apk成功)
    查看CentOS版本
    新建git仓库并与github同步
  • 原文地址:https://www.cnblogs.com/farb/p/4940132.html
Copyright © 2020-2023  润新知