zoukankan      html  css  js  c++  java
  • AutoMapper总结

    AutoMapper是一个对象和对象间的映射器。对象与对象的映射是通过转变一种类型的输入对象为一种不同类型的输出对象工作的。让AutoMapper有意思的地方在于它提供了一些将类型A映射到类型B这种无聊的事情的有趣惯例。只要类型B遵守AutoMapper已经建立的惯例,大多数情况下,映射两种类型零配置就可以了。

      首先,需要有source(源)和destination(目标)类型。默认情况下AutoMapper 只要Destination类型的成员名字与Source类型的成员名字匹配(成员名称不区分大小写),并且成员类型相同就直接会将值传递给Destination类型。
      AutoMapper只要做一次初始化就可以使用,因此最好的配置代码的地方应该在应用启动时。

    初始化处理(Profile实例)

      Initialize():实例化Mapper对象
      CreateMap():创建映射关系 Ex:Mapper.Initialize(cfg=>{ cfg.CreateMap<Source, Dest>(); });
      AddProfile:使用配置文件创建映射关系 Ex: Mapper.Initialize(cfg=>{cfg.AddProfile<MyProfile>(); });对于MyProfile对象需要继承Profile对象,并重写 Configure()方法。

    映射前后操作:  

      BeforeMap(): 在映射前执行的处理。Ex:BeforeMap((src, dest) => src.Value = src.Value + 1)
      AfterMap(): 在映射后执行的处理。 Ex:AfterMap((src, dest) => src.Name = "FengTest")

    条件映射

      ForMember():对于映射中成员的处理。
      Condition():对于条件映射处理,满足该条件才会给目标成员赋值。
      Ex:ForMember(dest => dest.Value, opt => opt.Condition(src => src.Value > 0 && src.Value < 130));

    命名惯例

      SourceMemberNamingConvention :源类型成员命名规则
      Ex: cfg.SourceMemberNamingConvention = new LowerUnderscoreNamingConvention(); //下划线命名法
      cfg.DestinationMemberNamingConvention :目标类型成员命名规则
      Ex: cfg.DestinationMemberNamingConvention = new PascalCaseNamingConvention(); //帕斯卡命名法

    替换字符

      ReplaceMemberName():将源成员名称中的字符替换成新的字符此方法必须在CreateMap之前
      Ex: cfg.ReplaceMemberName("Tool", "Car");

    前后缀

      RecognizePrefixes():识别源成员名称中的前缀字符 Ex: cfg.RecognizePrefixes("P");
      RecognizePostfixes():识别源成员名称中的后缀字符 Ex: cfg.RecognizePostfixes("L");
      此方法必须在CreateMap之前,并且默认是识别“Get”字符前缀
      ClearPrefixes(): 清除前缀 Ex:cfg.CliearPrefixes()

    全局过虑 

      ShouldMapField : 字段的映射条件 Ex: cfg.ShouldMapField = field => false; //不映射任何字段
      ShouldMapProperty:属性的映射条件
      Ex:cfg.ShouldMapProperty = pro => pro.GetMethod != null && pro.GetMethod.IsPrivate;
      此方法必须是源类型与目标类型都满足该条件才能映射处理,默认情况下AutoMapper只对公共成员做映射,如果想识别Private/internal,可以修改这两个属性值。

    构造函数 

      默认情况下,当目标类型的构造函数中的参数名称、类型与源类型成员的名称、类型相同,AutoMapper会自动映射。
      当构造函数的参数名称与目标成员的名称不同时,可使用ForCtorParam()方法指定。
      ForCtorParam() : 对构造函数参数映射Ex:ForCtorParam("age1",user=>user.MapFrom(src=>src.Age))

    条件对象映射器

      AddConditionalObjectMapper():符合条件后两个类型自动映射。
      Ex:cfg.AddConditionalObjectMapper().Where((s, d) => d.Name == s.Name + "Dto");

    成员配置

      AddMemberConfiguration():配置文件, 配置中的东西都是以该方法开始的。
      Ex:cfg.AddMemberConfiguration().AddMember<NameSplitMember>(); 默认配置
      AddName<ReplaceName>(r => r.AddReplace("B", "A")) 替换字符
      AddName<PrePostfixName>(p => p.AddStrings(pr => pr.Prefixes, "Get", "get"))识别前缀
      AddName<PrePostfixName>(p => p.AddStrings(pr => pr.Postfixes, "Set", "set"))识别后缀
      AddName<SourceToDestinationNameMapperAttributesMember>() 特性支持
      [MapToAttribute("Phone")] :特性,匹配基于给定名称的属性
      AutoMapper默认值:AddMemberConfiguration().AddMember<NameSplitMember>()
      .AddName<PrePostfixName>(_ => _.AddStrings(p => p.Prefixes,"Get"))
      .AddName<SourceToDestinationNameMapperAttributesMember>();
      AddName和AddMember中的每个类型都是基于ISourceToDestinationNameMapper和IChildMemberConfiguration接口的。也可以创建自己的类通过Lambda语句参数来配置属性,因此你可以微调AutoMapper如何解析属性映射。

    自定义类型转换 

      在作对象之间的转换时,有些属性的类型是不能直接转换的,但经过验证,默认可以将string类型映射为int和DateTime类型。  
    方法一:
    ConvertUsing() :使用映射的方式
    Ex: cfg.CreateMap<Source, Destination>().ConvertUsing(s =>
    {
    var d = new Destination();
    d.Value1 = System.Convert.ToInt32(s.Value1);
    d.Value2 = System.Convert.ToDateTime(s.Value2);
    d.Value3 = Type.GetType(s.Value3);
    return d;
    });
    方法二:
    定一个类,该类型需要继承 ITypeConverter泛型接口,源类型和目标类型,并且实现Convert方法
    Ex: public class CustomTypeConverter : ITypeConverter<Source, Destination>
    然后在Mapper.Initialize的时候使用ConvertUsing的泛型方法
    Ex: cfg.CreateMap<Source, Destination>().ConvertUsing<CustomTypeConverter>();
    方法三:
    定一个类,该类型需要继承ITypeConverter泛型接口,源基础类型和目标基础类型,并且实现Convert方法
    Ex:public class TypeConverter : ITypeConverter<string, Type>
    然后在Mapper.Initialize的时候创建该基类型的映射,该方式在Mapper全局都是有效的
    Ex: Mapper.Initialize(cfg => {
    cfg.CreateMap<string, Type>().ConvertUsing<TypeConverter>();
    cfg.CreateMap<Source, Destination>();
    });

    自定义值解析

      虽然AutoMapper覆盖了很大一部分目标成员的映射场景,但还是有一部分需要自定义处理。因是对目标类的中的某一个属性的赋值处理,因些会用到ForMember()方法。使用ResolveUsing() :指定赋值的方式。
    方法一:
    Ex:cfg.CreateMap<Source, Destination>().ForMember(dest => dest.Total, opt => {
    opt.ResolveUsing(s =>
    {
    var destination = new Destination();
    destination.Total = s.Value1 + s.Value2;
    return destination.Total;
    }); });
    方法二:
    创建一个类,并实现IValueResolver方法
    Ex: public class MyValueResolver : IValueResolver<Source, Destination, int>
    然后在创建映射关系的时候为其更改赋值方式
    Ex: cfg.CreateMap<Source, Destination>().ForMember(dest => dest.Total, opt => { opt.ResolveUsing<MyValueResolver>(); });

    Dynamic和ExpandoObject映射

    Dynamic动态创建对象 Ex:dynamic dynamicObj = new ExpandoObject();//ExpandoObject对象包含可在运行时动态添加或移除的成员.
    虽然Dynamic为动态对象不有办法创建映射关系,但必须先对Mapper实例化,才能使用。
    Ex: public static ExpandoObject DynamicAndExpandoObject()
    {
    Mapper.Initialize(cfg=> { });
    dynamic dynamicObj = new ExpandoObject();
    dynamicObj.Age = 12;
    dynamicObj.Name = "Feng测试";
    Person person = Mapper.Map<Person>(dynamicObj);
    Console.WriteLine("person.Age={0},Name={1}", person.Age, person.Name);
    dynamic dynamicSecond = Mapper.Map<ExpandoObject>(person);
    dynamicSecond.Address = "北京";
    Console.WriteLine("dynamicObj.Age={0},Name={1},Address={2}", dynamicSecond.Age, dynamicSecond.Name, dynamicSecond.Address);
    return dynamicSecond;
    }

    List和数组

    AutoMapper只要求元素类型的配置而不要求可能会用到的任何数组或者list类型。因此的创建映射的配置中,只是配置类型之间的映射,而不需要设计任何集合类型。
    具体来说,支持的源集合类型包括:
      • IEnumerable
      • IEnumerable<T>
      • ICollection
      • ICollection<T>
      • IList
      • IList<T>
      • List<T>
      • Arrays

    集合中的多态元素类型

    AutoMapper支持多态数组和集合,因此如果发现派生的源或者目标类型就会自动转换,但创建的时候需要声明。
    Ex:cfg.CreateMap<ParentSource, ParentDestination>().Include<ChildSource, ChildDestination>();
    但也需要声明子类型的映射,因为AutoMapper“猜不出”具体是哪个子类型
    Ex:cfg.CreateMap<ChildSource, ChildDestination>();
    也可以声明子类型的映射,再包含基类型,但也要再声明基类型的映射
    Ex:cfg.CreateMap<ParentSource, ParentDestination>();
    cfg.CreateMap<ChildSource, ChildDestination>().IncludeBase<ParentSource, ParentDestination>();

     

    Null值替换

    当源类型中某个属性为空值的时候在映射到目标类型时,目标类型的该属性可以设置一个默认值
    NullSubstitute(),如果源属性为空,则用该方法设置默认值。
    Ex: cfg.CreateMap<Person, PersonInfo>().ForMember(dest => dest.Title, opt => opt.NullSubstitute("屌丝"));
     
    学习来源:http://www.cnblogs.com/farb/p/4932692.html
  • 相关阅读:
    MSIL实用指南-一维数组的操作
    MSIL实用指南-给字段、属性、方法、类、程序集加Attribute
    MSIL实用指南-比较运算
    MSIL实用指南-逻辑运算
    MSIL实用指南-位运算
    MSIL实用指南-数学运算
    MSIL实用指南-创建对象
    MSIL实用指南-装箱拆箱
    MSIL实用指南-生成构造函数
    K8S从入门到放弃系列-(5)kubernetes集群之kube-apiserver部署
  • 原文地址:https://www.cnblogs.com/shiyilang398/p/11360518.html
Copyright © 2011-2022 走看看