ASP.NET Core-自动映射
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的类然后进行配置