对象映射工具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,完成了一个简单的定时任务处理解决方案. 本篇紧接着来玩一 ...
随机推荐
- sublime3破解版sublime3注册码
Sublime Text 3 官方网址:http://www.sublimetext.com/ Mac下载地址: http://c758482.r82.cf2.rackcdn.com/Sublime% ...
- objective-c中的@selector()和 c /c++的函数指针
先看tomcat里用到的代码: //然后开始动画 //把图片放到animationImages,接受数组参数 self.tom.animationImages = arrayImage; //设置时间 ...
- iframe编程的一些问题
前几天做一个用iframe显示曲线图的demo,发现对iframe的contentDocument绑定 onclick事件都无效,而在页面中对iframe.contentDocument的onclic ...
- Anliven - 一碗毒鸡汤
什么是你的核心动力,支撑着你持续前进? 什么是你的加速度,激发你全部的潜能和勇气? 你的核心动力应该来自于: 家人与朋友的信任.包容与期待 你本应承担的责任 对自己有所要求,有所期待,你本应更好 而你 ...
- 关于Java中的final关键字
Java中的final关键字是用来限制用户行为的,说白了,就是用来限制我们这些程序员的.final可以用来修饰:变量.方法.类. 1)Java final variable final用来修饰变量时, ...
- SQL Server SQL性能优化之--数据库在“简单”参数化模式下,自动参数化SQL带来的问题
数据库参数化的模式 数据库的参数化有两种方式,简单(simple)和强制(forced),默认的参数化默认是“简单”,简单模式下,如果每次发过来的SQL,除非完全一样,否则就重编译它(特殊情况会自动参 ...
- 创建实体数据模型【Create Entity Data Model】(EF基础系列5)
现在我要来为上面一节末尾给出的数据库(SchoolDB)创建实体数据模型: SchoolDB数据库的脚本我已经写好了,如下: USE master GO IF EXISTS(SELECT * FROM ...
- ActiveX(二)Js 监听 ActiveX中的事件
在上一篇随笔:ActiveX(一)第一个简单的Demo 中,已经可以实现 js 单向调用 ActiveX 中的方法,在很多情况下ActiveX中的方法的执行时相对耗时.耗性能的.在这样的情况下.Act ...
- iOS项目开发中的知识点与问题收集整理②(Part 二)
1.点击UIButton 无法产生触摸事件 如果在UIImageView中添加了一个按钮,你会发现在默认情况下这个按钮是无法被点击的,需要设置UIImageView的userInteractio ...
- 微信扫码支付~官方DEMO的坑~参数不能自定义
返回目录 由于微信在校验参数时采用了“微信服务端”校验,它的参数是前期定义好的,所以用户不能自己添加自定义的参数,你可以把参数写在Attach字段时,作为它的附加参数. 参数和返回值定义如下: pub ...