对象映射工具AutoMapper介绍
AutoMapper是用来解决对象之间映射转换的类库。对于我们开发人员来说,写对象之间互相转换的代码是一件极其浪费生命的事情,AutoMapper能够帮助我们节省不少时间。
一. AutoMapper解决了什么问题?
要问AutoMapper解决了什么问题? 难道不是对象映射转换的问题吗?
当然是,不过我们可以问深入一些,为什么项目中会出现大量的对象映射转换?(以下对于非MVC项目也适用)
在现代的软件开发中,项目的层级更加的细分,而不同层级之间对于对象的需求是有区别的,这就需要在不同层级间传递数据的时候,必须要转换数据。
举一些实际具体的例子:
在持久层(数据访问层), 我们的User对象,可能是一个包含User表中所有字段的数据的对象,甚至包含了用户的Password信息。而在界面层,我们只是需要显示用户的name, email,不需要Password这些额外的信息,同时,它还需要用户的考勤信息,而这个信息来自于另外一张表。
这个例子中,能够发现不同层之间,我们对于数据对象的需求是不同的。
每个层都做了它们职责范围内的事情:
持久层关注数据,所以只提供数据对象,它无需知道外层如何使用这些数据对象,也无法知道。
界面层关注数据的呈现,它只关注它要显示的数据。
那么问题是,谁来弥补它们之间的鸿沟?DTO(Data Transfer Object)——数据传输对象。而AutoMapper就是解决其中涉及到的数据对象转换的工具。
在实际开发中,如果你还可以直接在Business层或者界面层直接使用持久层的对象,因为你认为这个关系不大,整个项目都是你自己控制的,虽然dirty,但是quick. 作为一个有些洁癖的程序员,我还是建议使用DTO在不同层级之间传递数据。因为当你做更高层级开发的时候,比如开发web service,WCF,Web API这些为系统外部提供接口的开发时候,你就回明白这些好的习惯和思维能够帮助你更加好的设计这些外部接口。
二. AutoMapper如何使用?
先来看一个简单的例子,这个例子是定义Order对象到OrderDto对象之间的映射。(我们把Order称呼为源类,OrderDto称呼为目标类)
Mapper.CreateMap<Order, OrderDto>();//创建映射关系Order –> OrderDto
OrderDto dto = Mapper.Map<OrderDto>(order);//使用Map方法,直接将order对象装换成OrderDto对象
智能匹配
AutoMapper能够自动识别和匹配大部分对象属性:
- 如果源类和目标类的属性名称相同,直接匹配
- 目标类型的CustomerName可以匹配源类型的Customer.Name
- 目标类型的Total可以匹配源类型的GetTotal()方法
自定义匹配规则
AutoMapper还支持自定义匹配规则
Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
//属性匹配,匹配源类中WorkEvent.Date到EventDate
.ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.WorkEvent.Date))
.ForMember(dest => dest.SomeValue, opt => opt.Ignore())//忽略目标类中的属性
.ForMember(dest => dest.TotalAmount, opt => opt.MapFrom(src => src.TotalAmount ?? ))//复杂的匹配
.ForMember(dest => dest.OrderDate, opt => opt.UserValue<DateTime>(DateTime.Now));固定值匹配
测试
当定义完规则后,可以使用下面的代码来验证配置是否正确。不正确抛出异常AutoMapperConfigurationException.
Mapper.AssertConfigurationIsValid();
三. AutoMapper处理多对一映射
我们开篇提到的问题中,说到界面显示User的name, email, 还有用户的考勤信息,而这些信息来自于2张不同的表。这就涉及到了多对一映射的问题,2个持久层对象需要映射到一个界面显示层的对象。
假设我们的持久层对象是这样的:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Passworkd { get; set; }
public DateTime Birthday { get; set; }
} public class Evaluation
{
public int Id { get; set; }
public int Score { get; set; }
}
在Asp.net MVC中,我的界面显示层的ViewModel是这样的
public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Score { get; set; }
}
接下来,为了达到多对一的映射的目的,我们创建这个EntityMapper类
public static class EntityMapper
{
public static T Map<T>(params object[] sources) where T : class
{
if (!sources.Any())
{
return default(T);
} var initialSource = sources[];
var mappingResult = Map<T>(initialSource); // Now map the remaining source objects
if (sources.Count() > )
{
Map(mappingResult, sources.Skip().ToArray());
}
return mappingResult;
} private static void Map(object destination, params object[] sources)
{
if (!sources.Any())
{
return;
}
var destinationType = destination.GetType();
foreach (var source in sources)
{
var sourceType = source.GetType();
Mapper.Map(source, destination, sourceType, destinationType);
}
} private static T Map<T>(object source) where T : class
{
var destinationType = typeof(T);
var sourceType = source.GetType();
var mappingResult = Mapper.Map(source, sourceType, destinationType);
return mappingResult as T;
}
}
为了实现多个源对象映射一个目标对象,我们使用了AutoMapper的方法,从不同的源对象逐一匹配一个已经存在的目标对象。下面是实际使用在MVC中的代码:
public ActionResult Index()
{
var userId = ,
var user = _userRepository.Get(userId);
var score = _scoreRepository.GetScore(userId);
var userViewModel = EntityMapper.Map<UserViewModel>(user, score);
return this.View(userViewModel);
}
四. 使用Profile在Asp.net MVC项目中配置AutoMapper
Profile是AutoMapper中用来分离类型映射定义的,这样可以让我们的定义AutoMapper类型匹配的代码可以更加分散,合理和易于管理。
利用Profile, 我们可以更加优雅的在MVC项目中使用我们的AutoMapper. 下面是具体的方法:
1. 在不同层中定义Profile,只定义本层中的类型映射
继承AutoMapping的Profile类,重写ProfileName属性和Configure()方法。
public class ViewModelMappingProfile: Profile
{
public override string ProfileName
{
get
{
return GetType().Name;
}
} protected override void Configure()
{
Mapper.CreateMap......
}
}
2. 创建AutoMapperConfiguration, 提供静态方法Configure,一次加载所有层中Profile定义
public class AutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(x => x.AddProfile<ViewModelMappingProfile>());
Mapper.AssertConfigurationIsValid();
}
}
3. 在Global.cs文件中执行
最后,在Global.cs文件中程序启动前,调用该方法
AutoMapperConfiguration.Configuration()
对象映射工具AutoMapper介绍的更多相关文章
- .NET的对象映射工具AutoMapper使用笔记
AutoMapper是一个.NET的对象映射工具. 项目地址:https://github.com/AutoMapper/AutoMapper. 帮助文档:https://github.com/Aut ...
- EF架构~AutoMapper对象映射工具简化了实体赋值的过程
回到目录 AutoMapper是一个.NET的对象映射工具,一般地,我们进行面向服务的开发时,都会涉及到DTO的概念,即数据传输对象,而为了减少系统的负载,一般我们不会把整个表的字段作为传输的数据,而 ...
- .NET之AutoMapper对象映射工具运用
AutoMapper对象映射工具:主要是将某一个实体转成另一个实体. 1.引用NuGet包;搜索:AutoMapper 2.创建实体类 using System; using System.Colle ...
- .NET的DTO映射工具AutoMapper
.NET的DTO映射工具AutoMapper 原文:https://github.com/AutoMapper/AutoMapper/wiki/Getting-started 参考:http://ww ...
- 【5min+】 对象映射只有AutoMapper?试试Mapster
系列介绍 [五分钟的dotnet]是一个利用您的碎片化时间来学习和丰富.net知识的博文系列.它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net ...
- 对象转换工具 MapStruct 介绍
前言 在我们日常开发的分层结构的应用程序中,为了各层之间互相解耦,一般都会定义不同的对象用来在不同层之间传递数据,因此,就有了各种 XXXDTO.XXXVO.XXXBO 等基于数据库对象派生出来的对象 ...
- ASP.NET Core 中的对象映射之 AutoMapper
目录 AutoMapper 简介 AutoMapper 使用 初始化 Profile设置 扁平化映射 集合映射 投影 条件映射 值转换 设置转换前后行为 配置验证及设置 反向映射 自定义转换器 自定义 ...
- [转]对象映射类AutoMapper的使用
由于原文太长了,此处就直接贴上原文的超链接,大家自行学习. codeproject中的一篇文章: AutoMapper
- 基于 abp vNext 和 .NET Core 开发博客项目 - 用AutoMapper搞定对象映射
上一篇文章(https://www.cnblogs.com/meowv/p/12961014.html)集成了定时任务处理框架Hangfire,完成了一个简单的定时任务处理解决方案. 本篇紧接着来玩一 ...
随机推荐
- 如何通过一个类名找到它属于哪个jar包?
最简单的方式: 如果用eclipse选中类名,然后ctrl shift T,就可看到包含比类的包了 最有效的方式: import java.net.URL; /** * 检查class文件属于哪个ja ...
- table-cell实现宽度自适应布局
利用table-cell可以实现宽度自适应布局. table-cell有一些比较好用的属性,比如垂直居中,自适应高度宽度等,为元素设置table-cell布局之后,元素的margin失效,paddin ...
- Java位运算总结-leetcode题目
按位操作符只能用于整数基本数据类型中的单个bit中,操作符对应表格: Operator Description & 按位与(12345&1=1,可用于判断整数的奇偶性) | 按位或 ^ ...
- Node.js连接Mysql,并把连接集成进Express中间件中
引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...
- 项目积累html标签
今天遇到一个不太常用都标签,网上以后慢慢记下项目中用到都东西. 1.<em> 标签 告诉浏览器把其中的文本表示为强调的内容.对于所有浏览器来说,这意味着要把这段文字用斜体来显示. 在文本中 ...
- HTTP2特性预览和抓包分析
背景 近年来,http网络请求量日益添加,以下是httparchive统计,从2012-11-01到2016-09-01的请求数量和传输大小的趋势图: 当前大部份客户端&服务端架构的应用程序, ...
- 利用简洁的图片预加载组件提升h5移动页面的用户体验
在做h5移动页面,相信大家一定碰到过页面已经打开,但是里面的图片还未加载出来的情况,这种问题虽然不影响页面的功能,但是不利于用户体验.抛开网速的原因,解决这个问题有多方面的思路:最基本的,要从http ...
- 数据结构(c语言第2版)-----了解链表,栈,队列,串
关于链表我觉得这都是最基本的东西,但是不常见,在实际的应用中很少的使用,了解它会用就OK,不需要研究的那么深,除非做那种内存压缩,存储方面工作. C语言中动态申请空间 malloc() q=(dlin ...
- StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改
前言 使用StackExchange.Redis没有直接相关的方法进行模糊查询的批量删除和修改操作,虽然可以通过Scan相关的方法进行模糊查询,例如:HashScan("hashkey&qu ...
- poj1113--凸包(Andrew)
题目大意: 给出平面上若干个点的坐标,你的任务是建一个环形围墙,把所有的点围在里面,且距所有点的距离不小于l.求围墙的最小长度. 思路: 很容易得出答案就是凸包周长+以l为半径的圆的周长. 这里讲一下 ...