ASP.NET Core 3.1使用AutoMapper(基本使用)
AutoMapper定义
AutoMapper是一个OOM(Object-Object-Mapping)组件,从它的英文名字中可以看出,AutoMapper主要是为了实现实体间的相互转换,从而避免我们每次采用手工的方式进行转换。在没有OOM这类组件之前,如果我们需要实现实体之间的转换,只能使用手工修改代码,然后逐个赋值的方式实现映射,而有了OOM组件,可以很方便的帮助我们实现这一需求。
在学习EF的时候我们知道了ORM(Object Relational Mapping)映射,是一种对象关系的映射,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。而Automapper是一种实体转换关系的模型,AutoMapper是一个.NET的对象映射工具。主要作用是进行领域对象与模型(DTO)之间的转换、数据库查询结果映射至实体对象。
下边的是基本原理,大家喵一眼就行:
Ø 什么是DTO?
数据传输对象(DTO)(DataTransfer Object),是一种设计模式之间传输数据的软件应用系统。数据传输目标往往是数据访问对象从而从数据库中检索数据。数据传输对象与数据交互对象或数据访问对象之间的差异是一个以不具有任何行为除了存储和检索的数据(访问和存取器)。
Ø 为什么用?
它的目的只是为了对领域对象进行数据封装,实现层与层之间的数据传递。为何不能直接将领域对象用于数据传递?因为领域对象更注重领域,而DTO更注重数据。不仅如此,由于“富领域模型”的特点,这样做会直接将领域对象的行为暴露给表现层。
需要了解的是,数据传输对象DTO本身并不是业务对象。数据传输对象是根据UI的需求进行设计的,而不是根据领域对象进行设计的。比如,Customer领域对象可能会包含一些诸如FirstName, LastName, Email, Address等信息。但如果UI上不打算显示Address的信息,那么CustomerDTO中也无需包含这个 Address的数据”。
Ø 什么是领域对象?
领域模型就是面向对象的,面向对象的一个很重要的点就是:“把事情交给最适合的类去做”,即:“你得在一个个领域类之间跳转,才能找出他们如何交互”。在我们的系统中Model(EF中的实体)就是领域模型对象。领域对象主要是面对业务的,我们是通过业务来定义Model的。
配置AutoMapper
步骤一:引入Nuget程序包:AutoMapper 和 AutoMapper.Extensions.Microsoft.DependencyInjection
AutoMapper.Extensions.Microsoft.DependencyInjection,这个是用来配合依赖注入的;
步骤二:添加映射类 CustomProfile.cs
在你的项目中,添加一个AutoMapper文件夹(非必须),在新建个类,取名CustomProfile(这个名字可以自定义),此类必须继承于Profile,用来匹配所有的映射对象关系
1 using AutoMapper; 2 using GreenUnity.EntityFramework.Models; 3 using QG_EnterpriseAccountAPi.RequestModels; 4 using System; 5 using System.Collections.Generic; 6 using System.Text; 7 8 namespace QG_EnterpriseAccountAPi.AutoMapper 9 { 10 public class CustomProfile : Profile 11 { 12 /// <summary> 13 /// 配置构造函数,用来创建关系映射 14 /// </summary> 15 public CustomProfile() 16 { 17 //第一个参数是原对象,第二个是目的对象。ReverseMap代表着两个对象能够相互转换 18 CreateMap<Enterpriseowncheck,TbEnterpriseowncheck>().ReverseMap(); 19 20 } 21 } 22 }
Profile不知有什么用,通过百度了解才了解是services.AddAutoMapper是会自动找到所有继承了Profile的类然后进行配置,而且我的这个配置文件是在api层的,如果Profile配置类放在别的层(比如Service层),如果没解耦的话,可以services.AddAutoMapper(),参数留空,AutoMapper会从所有引用的程序集里找继承Profile的类,如果解耦了,就得services.AddAutoMapper(Assembly.Load("Blog.Core.Service"))。
Profile的用处在于告诉AutoMapper服务去哪里找映射关系, 在DI注入AutoMapper服务的时候如果继承Profile的类的程序集没有跟主项目解耦,就会去引用的程序集中找到所有继承Profile的类,如果解耦了,就需要使用反射加载继承Profile的类的程序集。
注入AutoMapper
在Startup中,注入服务
#region AutoMappe services.AddAutoMapper(typeof(Startup));//这是AutoMapper的2.0新特性 //services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());//与上面注入方式无区别 //services.AddAutoMapper(Assembly.Load("程序集Dll名称"));//解耦时需要使用反射加载程序集 #endregion
使用AutoMapper模型映射
1.在需要使用AutoMapper模型映射的类中注入IMapper
IMapper _IMapper; public EnterpriseOwnCheckController(UnitOfWork unit, ILogger<UserController> logger, IMapper IMapper) : base(unit, logger) { _IMapper = IMapper;//构造函数注入IMapper }
2.使用IMapper对象的Map方法实现对象的映射
//注意:<>里是需要转换成的对象(对象名称)。()里是被转换的对象(已实列化的对象名) var TbEnterpriseowncheck = _IMapper.Map<TbEnterpriseowncheck>(enterpriseowncheck);
复杂深拷贝映射
有的小伙伴问,你这个这个简单,都是相同字段的,那当然很方便啦,要是一个复杂的,比如属性名字不一样的,或者说有子类等嵌入型的咋办?放心,一样是可以的,请看
1、属性名称不一样(手动告诉AutoMapper 属性名称不一样的字段分别对应哪些字段)
CreateMap<Student, StudentViewModel>() .ForMember(d => d.CountyName, o => o.MapFrom(s => s.County)) .ForMember(d => d.ProvinceName, o => o.MapFrom(s => s.Province));
2、如果是还有子类的复杂类型
CreateMap<Student, StudentViewModel>() .ForMember(d => d.County, o => o.MapFrom(s => s.Address.County)) .ForMember(d => d.Province, o => o.MapFrom(s => s.Address.Province)) .ForMember(d => d.City, o => o.MapFrom(s => s.Address.City)) .ForMember(d => d.Street, o => o.MapFrom(s => s.Address.Street)) ; public class Student : Entity { public string Name { get; private set; } public string Email { get; private set; } public string Phone { get; private set; } public DateTime BirthDate { get; private set; } public Address Address { get; private set; } } public class StudentViewModel { public Guid Id { get; set; } public string Name { get; set; } public string Email { get; set; } public DateTime BirthDate { get; set; } public string Phone { get; set; } public string Province { get; set; } public string City { get; set; } public string County { get; set; } public string Street { get; set; } }
大部分资料参考来源:https://www.cnblogs.com/laozhang-is-phi/p/9565227.html#autoid-5-4-0
AutoMapper官网:https://docs.automapper.org/en/latest/index.html