今天刚看到老张的哲学博客关于AutoMapper的教程,从壹开始先后端分离【 .NET Core2.0 +Vue2.0 】框架之十三 || DTOs 对象映射使用,项目部署Windows+Linux完整版, 看得我有点晕,我搞不得那个CustomProfile跟AutoMapperProfile是干什么用的,可能我水平也比较菜,理解能力差点,而后我经过百度后,发现这个确实就是一个很简单的东西。html
主要分四步后端
注:我在第一次安装Nuget包时出现一个比较奇怪的状况,就是我先安装的AutoMapper.Extensions.Microsoft.DependencyInjection包,而后直接在Web层测试怎么用AutoMapper,学会后我想把Profile放到Service层后,而后在Service层上安装AutoMapper包,而后按F6生成解决方案后,发现依赖包就自动消失了,弄了很久次,一按F6,AutoMapper包就自动消失,我一直搞不懂为何,而后我把整个解决方案里AutoMapper相关的代码跟依赖包都删了,而后再安装个AutoMapper跟AutoMapper.Extensions.Microsoft.DependencyInjection,就正常了,后面我想重现以前的问题,但发现我怎么装都正常了,这是个很奇怪的问题,我也搞不懂为何。app
如下是个人解决方案目录,第一个红圈是Web层,第二个红圈是Service层,我把映射的Profile放在Service层的AutoMapper目录,由于我以为映射就是Service该干的活框架
这是实体类SysUser,我放在了Entity层前后端分离
public class SysUser { [Key] public int Id { get; set; } public string LoginName { get; set; } public string Name { get; set; } }
这是SysUser对应的DTO类SysUserDTO,我放在了DTO层,注意那个TestName字段,是我等下用来演示用的ide
public class SysUserDTO { public int Id { get; set; } public string LoginName { get; set; } public string Name { get; set; } public string TestName { get; set; } }
而后我在Service里建立一个文件夹AutoMapper,建立一个MapperProfile.cs类,记得安装AutoMapper包函数
MapperProfile.cs,我目前是把全部实体跟DTO的映射都写在一个Profile类中,就是建立不少个CreateMappost
using AutoMapper; using System; using System.Collections.Generic; using System.Text; using ItSys.Entity; using ItSys.DTO; namespace ItSys.Service.AutoMapper { public class MapperProfile : Profile { public MapperProfile() { //建立SysUser往SysUserDTO转换的映射,ReverseMap是建立反向映射,不过我发现若是都是同名的属性的话,没加这个ReverseMap也是能反向映射的 CreateMap<SysUser, SysUserDTO>().ReverseMap(); } } }
而后在Web层的Startup.cs类里的ConfigureServices方法里AddAutoMapper(记得安装AutoMapper.Extensions.Microsoft.DependencyInjection包),这个方法会自动找到全部继承了Profile类的配置类进行映射配置测试
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddAutoMapper(); }
注意这个方法若是像我上面这样写的话,就会获取全部引用的程序集里全部继承了Profile类的派生类进行配置,因此我即便Profile放在Service层里也是能获取到的,固然你也能够传入一个程序集参数,例如这样:AddAutoMapper(Assembly.GetAssembly(typeof(BaseService<>))),或者传入一个类AddAutoMapper(typeof(BaseService<>)),那AutoMapper就只会在程序集或类的程序集范围内查找了。this
而后我在SysUserService类里就能够这样写了,注意红色的代码
using System; using System.Collections.Generic; using System.Text; using ItSys.DTO; using ItSys.Repository.Sys; using ItSys.Entity; using AutoMapper; namespace ItSys.Service.Sys { public class SysUserService : BaseService<SysUser> { private IMapper _mapper; protected SysUserRepository repository; public SysUserService(SysUserRepository repository,IMapper mapper) { base.baseRepository = repository; this.repository = repository; _mapper = mapper; } public virtual SysUserDTO GetById(int id) { var sysUserEntity = repository.GetById(id); if (sysUserEntity == null) { throw new Exception("没找到数据"); } return _mapper.Map<SysUserDTO>(sysUserEntity); } } }
因此AutoMapper使用起来就是这么简单的。
对了,关于那个SysUserDTO的TestName字段,若是我想这个字段等于SysUser的LoginName跟Name字段相连的字符串,怎么弄的,很简单,在那个MapperProfile类中这么写
using AutoMapper; using System; using System.Collections.Generic; using System.Text; using ItSys.Entity; using ItSys.DTO; namespace ItSys.Service.AutoMapper { public class MapperProfile : Profile { public MapperProfile() { //建立SysUser往SysUserDTO转换的映射,ReverseMap是建立反向映射,若是都是同名的属性的话,没加这个ReverseMap也是能反向映射的,不过像如下这个有特殊属性的,就得加ReverseMap才能正常反向映射 CreateMap<SysUser, SysUserDTO>() .ForMember(destinationObject => destinationObject.TestName, options => { //目标类的TestName等于实体类的LoginName加上Name字段 options.MapFrom(sourceObject => sourceObject.LoginName + sourceObject.Name); }) .ReverseMap(); } } }