今天剛看到老張的哲學博客關於AutoMapper的教程,從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十三 || DTOs 對象映射使用,項目部署Windows+Linux完整版, 看得我有點暈,我搞不得那個CustomProfile跟AutoMapperProfile是乾 ...
今天剛看到老張的哲學博客關於AutoMapper的教程,從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十三 || DTOs 對象映射使用,項目部署Windows+Linux完整版, 看得我有點暈,我搞不得那個CustomProfile跟AutoMapperProfile是乾什麼用的,可能我水平也比較菜,理解能力差點,然後我通過百度後,發現這個確實就是一個很簡單的東西。
主要分四步
- 安裝Nuget依賴包 AutoMapper(我安裝時是8.1版本,這個包在你Web層跟放Profile類的層上),AutoMapper.Extensions.Microsoft.DependencyInjection(依賴註入的,主要是用到一個AddAutoMapper方法,這個是安裝在Web層的),如果你沒有分層的話,你也可以只安裝個AutoMapper.Extensions.Microsoft.DependencyInjection就行了,因為這個包本身就依賴AutoMapper包;
- 創建繼承Profile類(這是AutoMapper的配置類)的子類,這個是用來配置實體跟DTO的映射的配置;
- 在Web層的Startup.cs的ConfigureServices方法中增加services.AddAutoMapper(),這個方法會獲取程式集里所有繼承Profile類的派生類進行註冊並把IMapper註入到服務容器里;
- 然後就可以在Controller或Service里通過構造函數註入IMapper,然後用mapper.map<>()進行實體與DTO的轉換了。
註:我在第一次安裝Nuget包時出現一個比較奇怪的情況,就是我先安裝的AutoMapper.Extensions.Microsoft.DependencyInjection包,然後直接在Web層測試怎麼用AutoMapper,學會後我想把Profile放到Service層後,然後在Service層上安裝AutoMapper包,然後按F6生成解決方案後,發現依賴包就自動消失了,弄了好久次,一按F6,AutoMapper包就自動消失,我一直搞不懂為什麼,然後我把整個解決方案里AutoMapper相關的代碼跟依賴包都刪了,然後再安裝個AutoMapper跟AutoMapper.Extensions.Microsoft.DependencyInjection,就正常了,後面我想重現之前的問題,但發現我怎麼裝都正常了,這是個很奇怪的問題,我也搞不懂為什麼。
以下是我的解決方案目錄,第一個紅圈是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欄位,是我等下用來演示用的
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類中,就是創建很多個CreateMap
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就只會在程式集或類的程式集範圍內查找了。
然後我在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(); } } }