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;
}

扁平化

性相匹配。 如果对目标类型上的任何属性,方法或以“Get”为前缀的方法不存在源类型上,则AutoMapper会将目标成员名称拆分为单个单词(遵循帕斯卡(PascalCase)拼写法约定)。 
Ex:public class Order
{
public Customer Customer { get; set; }
public decimal GetTotal()
{
return 100M;
}
}
public class Customer
{
public string Name { get; set; }
}
public class OrderDto
{
public string CustomerName { get; set; }
public decimal Total { get; set; }
}
当使用 Order与OrderDto映射时,Total属性匹配到了Order上的GetTotal方法。CustomerName属性匹配到了Order上的Customer.Name属性。总之,只要合适地命名目标类型属性,我们就不必配置单独的属性匹配。

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>();

继承映射属性

对一个属性的映射有多种方式,下面是这些源的优先级
    • 显式映射 (使用.MapFrom())
    • 继承的显式映射
    • 默认的映射 (通过默认匹配的属性)
    • 忽略的属性映射
Ex: cfg.CreateMap<Order, OrderDto>().Include<PCOrder, OrderDto>().Include<MobileOrder, OrderDto>().ForMember(o => o.Referrer, m => m.Ignore());//这里配置了忽略目标属性Referrer的映射
虽然在配置中忽略了Referrer的映射处理,但还是会将源类型中的Referrer属性值给到目标。这就是优先级的问题。这就是因为 默认的映射比忽略的映射优先级高。

Null值替换

当源类型中某个属性为空值的时候在映射到目标类型时,目标类型的该属性可以设置一个默认值
NullSubstitute(),如果源属性为空,则用该方法设置默认值。
Ex: cfg.CreateMap<Person, PersonInfo>().ForMember(dest => dest.Title, opt => opt.NullSubstitute("屌丝"));

开放泛型

所谓的开放泛型是指 源类型为一个泛型类,目标类型也是一个泛型类型。在创建两个泛型类的映射时,中的泛型不需要填写。
Ex: cfg.CreateMap(typeof(Source<>), typeof(Destination<>));
也可以使用一个泛型转换器来进行处理。
Ex: cfg.CreateMap(typeof(Source<>),typeof(Destination<>))
.ConvertUsing(typeof(Converter<>));

投影

当把一个源值投影到一个不精准匹配源结构的目标值时,必须指明成员映射定义。
MapFrom() :指定源类型属性的值。
Ex: .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
 
学习来源:http://www.cnblogs.com/farb/p/4932692.html
 
 
 
 
 
 

AutoMapper总结的更多相关文章

  1. 恋爱虽易,相处不易:当EntityFramework爱上AutoMapper

    剧情开始 为何相爱? 相处的问题? 女人的伟大? 剧情收尾? 有时候相识即是一种缘分,相爱也不需要太多的理由,一个眼神足矣,当EntityFramework遇上AutoMapper,就是如此,恋爱虽易 ...

  2. 【AutoMapper官方文档】DTO与Domin Model相互转换(上)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

  3. AutoMapper

    什么是AutoMapper? AutoMapper是一个对象和对象间的映射器.对象与对象的映射是通过转变一种类型的输入对象为一种不同类型的输出对象工作的.让AutoMapper有意思的地方在于它提供了 ...

  4. AutoMapper随笔记

    平台之大势何人能挡? 带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4822808.html#skill 先看效果:(完整Demo:https://git ...

  5. AutoMapper:Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type

    异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 应用场景:ViewModel==>Mode映射的时候出错 AutoMappe ...

  6. AutoMapper的介绍与使用(一)

    软件环境 vs2015 asp.net mvc 5 .NET Framework 4.5.2 AutoMapper 5.2.0.0 AutoMapper安装 新建asp.net mvc 项目 Auto ...

  7. AutoMapper使用中的问题

    指定值只会执行一次 public class MomanBaseProfile : Profile { public MomanBaseProfile() { CreateMap<Request ...

  8. 【AutoMapper官方文档】DTO与Domin Model相互转换(中)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

  9. 【AutoMapper官方文档】DTO与Domin Model相互转换(下)

    写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...

  10. 【道德经】漫谈实体、对象、DTO及AutoMapper的使用

    写在前面 实体和值对象 实体和对象 故常无欲以观其妙,常有欲以观其徼 初始实体和演化实体 代码中的DTO AutoMapper实体转换 后记 实体(Entity).对象(Object).DTO(Dat ...

随机推荐

  1. Cesium之球心坐标与本地坐标

    1球心坐标(ECEF)与本地坐标(NEU) 假如你来到一个陌生城市,你很可能需要问路.通常会告诉你向北走100米,右转,向东走100米,理解起来很直观.你给儿子买了一个地球仪,你从北京(39,115) ...

  2. Spring+SpringMVC+MyBatis+easyUI整合优化篇(九)数据层优化-jdbc连接池简述、druid简介

    日常啰嗦 终于回到既定轨道上了,这一篇讲讲数据库连接池的相关知识,线程池以后有机会再结合项目单独写篇文章(自己给自己挖坑,不知道什么时候能填上),从这一篇文章开始到本阶段结束的文章都会围绕数据库和da ...

  3. 2.Ubuntu16.04安装QT5.8.0

    VSCode编辑器开发CPP:http://www.cnblogs.com/dotnetcrazy/p/6661921.html 下载QT run文件(安装包),一般都是这两个下载的比较多,我这边使用 ...

  4. Laravel框架一:原理机制篇

    Laravel作为在国内国外都颇为流行的PHP框架,风格优雅,其拥有自己的一些特点.以下是本人一点粗浅的认识,不敢奢求他人同意,更不能一一而足,仅为自己做一点总结而已. 一. 请求周期 Laravel ...

  5. Google Earth影像数据破解之旅

    "Zed, you are so excellent." 为什么要写这句英文?容我卖个关子稍后再解释. 相信大多数人都体验过Google Earth(简称GE),我对GE最初的印象 ...

  6. 商城项目实战 | 2.2 Android 仿京东商城——自定义 Toolbar (二)

    本文为菜鸟窝作者刘婷的连载."商城项目实战"系列来聊聊仿"京东淘宝的购物商城"如何实现. 上一篇文章<商城项目实战 | 2.1 Android 仿京东商城 ...

  7. python基本数据类型——dict

    一.创建字典: d = { "name": "morra", #字典是无序的 "age": 99, "gender": ...

  8. Python中使用with语句同时打开多个文件

    下午小伙伴问了一个有趣的问题, 怎么用 Python 的 with 语句同时打开多个文件? 首先, Python 本身是支持同时在 with 中打开多个文件的 with open('a.txt', ' ...

  9. 第一篇 Rewrite规则简介

    1.Rewirte主要的功能就是实现URL的跳转,它的正则表达式是基于Perl语言.可基于服务器级的(httpd.conf)和目录级的(.htaccess)两种方式.如果要想用到rewrite模块,必 ...

  10. Python标准模块—Regular Expressions

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 1 模块简介 正则表达式是一门小语言,你可以在Python中或者其 ...