1.安裝NuGet包AutoMapper
2.建立示例Entity、Dto
Entity
public class User { public long Id { get; set; } /// <summary> /// 賬號 /// </summary> public string UserName { get; set; } /// <summary> /// 名字 /// </summary> public string Name { get; set; } public string Password { get; set; } /// <summary> /// 使用者是否鎖定 /// </summary> public bool IsLockoutEnabled { get; set; } public string PhoneNumber { get; set; } }
Dto
public class UserDto { public string UserName { get; set; } /// <summary> /// 名字 /// </summary> public string Name { get; set; } public string Password { get; set; } /// <summary> /// 使用者是否鎖定 /// </summary> [PropertyMapper(SourceName = "IsLockoutEnabled")] public bool IsLock { get; set; } public string PhoneNumber { get; set; } }
3.配置對映關係-AutoMapperMappingProfile
/// <summary> /// 這裡的 Profile作用是Program中services.AddAutoMapper時它會自動找到所有繼承了Profile的類然後進行配置 /// </summary> public class AutoMapperMappingProfile:Profile { public AutoMapperMappingProfile() { CreateMap<User, UserDto>().ReverseMap();//ReverseMap雙向對映 } }
注:預設是欄位同名自動對映,若欄位不同名則需要設定對映規則
4.Program.cs中注入對映服務
builder.Services.AddAutoMapper(typeof(AutoMapperMappingProfile));
5.使用
[ApiController] [Route("[controller]")] public class UserController(IUserService userService,IMapper mapper) : ControllerBase { [HttpGet("GetSingleUserInfo")] public async Task<UserDto> GetSingleUserInfo(string account) { var info= await userService.GetSingleUserInfo(account); return mapper.Map<UserDto>(info); } }
對映配置改進
針對以上的對映來說,每次有新的對映關係都需要到AutoMapperMappingProfile配置檔案中配置,這種方式操作起來顯得繁瑣,還可能會遺忘,為了方便操作,做了以下改進,讓每一個對映關係自動加入到配置中
1.建立特性PropertyMapperAttribute
/// <summary> /// ValidOn 規定特性可被使用的範圍它是列舉器 AttributeTargets的值的組合。預設值是 AttributeTargets.All表示在所有元素都可使用。如果只允許在類或者屬性上使用可以定義:AttributeTargets.Class或者AttributeTargets.Property /// AllowMultiple(可選的)bool型別。如果為 true,則該特性是多用的。預設值是 false(單用的) /// Inherited(可選的)bool型別。如果為 true,則該特性可被派生類繼承。預設值是 false(不被繼承) /// </summary> [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class PropertyMapperAttribute:Attribute { public string SourceName { get; set; } //public Type SourceType { get; set; } }
2.在需要對映的Dto中新增特性
AutoMapAttribute,AutoMapper包自帶的特性用於明確對映物件,新增至類中
PropertyMapperAttribute,用於屬性的特性,本次用來表明對映的欄位(當對映雙方欄位不相同時)
[AutoMap(typeof(User))] public class UserDto { public string UserName { get; set; } /// <summary> /// 名字 /// </summary> public string Name { get; set; } public string Password { get; set; } /// <summary> /// 使用者是否鎖定 /// </summary> [PropertyMapper(SourceName = "IsLockoutEnabled")] public bool IsLock { get; set; } public string PhoneNumber { get; set; } }
3.對映配置檔案改進-BatchAutoMapperProfile
/// <summary> /// 自動新增對映配置(需使用特性AutoMapAttribute的DTO) /// </summary> public class BatchAutoMapperProfile:Profile { public BatchAutoMapperProfile() { InitMapper(); } private void InitMapper() {//尋找應用中所有包含TestApp(應用名稱)的程式集,且找程式集中名稱中帶Dto的類 var allTypeses = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.Contains("TestApp")).SelectMany(a => a.GetTypes()).Where(a=>a.Name.Contains("Dto")).ToArray();//.Where(a => a.FullName.Contains("PlantAtlas.Interface")|| a.FullName.Contains("PlantAtlas.Server")).ToArray(); //類對映配置 var typeList =allTypeses.Where(t=>t.GetCustomAttributes(typeof(AutoMapAttribute)).Any()).ToList();//過濾類中帶有AutoMapAttribute特性標籤的類 typeList.ForEach(type => { var attribute = (type.GetCustomAttributes(typeof(AutoMapAttribute)).FirstOrDefault()); if (attribute != null) { var a = (AutoMapAttribute)attribute; if (a.SourceType == null) return; var mapper = CreateMap(a.SourceType, type);//.ReverseMap(); //類屬性對映配置 var propertyList = type.GetProperties().Where(t => t.GetCustomAttributes(typeof(PropertyMapperAttribute)).Any()).ToList();//過濾出帶有PropertyMapperAttribute特性的屬性做特殊對映 propertyList.ForEach(pro => { var property = pro.GetCustomAttributes<PropertyMapperAttribute>().FirstOrDefault(); if (property != null && !string.IsNullOrEmpty(property.SourceName)) { mapper.ForMember(pro.Name, src => src.MapFrom(property.SourceName)); } }); mapper.ReverseMap();//ReverseMap表示雙向對映 } }); } }
4.Program.cs中注入對映服務
//自動對映 builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
注:AddAutoMapper中傳入的參數列明是那個範圍內找所有繼承了Profile的類然後進行配置