目录
前言
此文介绍
AutoMapper
和Mapster
的简单使用和配置
两者都用于 : 自动映射 实体Entity
与 视图DTO
AutoMapper
四步骤:
- 导入依赖
- 创建配置文件
- 创建自定义映射文件
Program
中注册配置文件
1. 导入依赖
- Nuget包
- ( 类库项目可在Service层导入 )
AutoMapper.Extensions.Microsoft.DependencyInjection
2. 创建配置文件
- 项目 中 可创建一个
Extension
拓展类库 添加配置文件
namespace WebProject.Extension;
/// <summary>
/// 静态全局 AutoMapper 配置文件
/// </summary>
public class AutoMapperConfig
{
public static MapperConfiguration RegisterMappings()
{
// 引入自定义配置信息文件CustomProfile
return new MapperConfiguration(cfg => { cfg.AddProfile(new CustomProfile()); });
}
}
3. 创建自定义配置信息文件 Profile
- 自定义文件 继承
Profile
类
namespace WebProject.Extension;
public class CustomProfile : Profile
{
/// <summary>
/// 配置构造函数,用来创建关系映射
/// </summary>
public CustomProfile()
{
// 实体内部属性名字如果都一样就直接将类关联
CreateMap<User, UserDto>();
// 实体内部属性命名不同或有特殊的设置,需要将属性字段一一对应
CreateMap<Role, RoleDto>()
.ForMember(d => d.Name,
opt => opt.MapFrom(src => src.RoleName));
}
}
4. Program
注册
// 配置注册AutoMapper
builder.Services.AddAutoMapper(typeof(AutoMapperConfig));
AutoMapperConfig.RegisterMappings();
使用
- 在Service层 进行视图模型Dto与实体Entity的绑定
_mapper.Map<List<XXDto>>(Entity)
_mapper.Map<List<目标>(来源)
public class TestServices : ITestService
{
private ITestRepository _testRepository; // 仓储层 与数据库关联的层级
private readonly IMapper _mapper; // 添加AutoMapper依赖注入
// 这里使用构造注入
public TestServices(ITestRepository testRepository, IMapper mapper)
{
_testRepository = testRepository;
_mapper = mapper;
}
// 查询方法 返回 List<UserDto> 数据
// 这里需要将实体Entity 转换成 Dto 返回给Controller层提供给前端
public async Task<List<UserDto>> Query()
{
var entities = await _testRepository.Query(); //获取到实体Entity对象
return _mapper.Map<List<UserDto>>(entities); // 使用
}
}
Mapster1
同样四步骤:
- 导入依赖
- 创建配置文件
- 自定义映射规则
- 注册配置文件
1. 导入依赖
添加Mapster
依赖 Nuget下载,同样类库项目放在Service层
其实如果 属性字段命名相同,配置文件都不用写,导入完依赖,在Service层使用
Adapt<>
方法直接 就可以自动映射实体与视图
举例 :
// 当实体名字对应 不用再写自定义配置文件(:Profile) 直接用
// var 目标 = 来源.Adapt<目标>();
var userDto = userEntity.Adapt<UserDto>();
// Entity.Adapt<Dto>();
2. 创建配置文件
当命名不同时:
- 以下为自动配置 2工具类 ,直接用
namespace ProjectWebApi.Common.Mapster;
/// <summary>
/// 实现Mapster的IRegister自动映射
/// </summary>
public static class ImplAutoIRegisterExtensions
{
/// <summary>
/// 添加对象映射
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="assemblies">扫描的程序集</param>
public static IServiceCollection AddMapsterIRegister(this IServiceCollection services, params Assembly[] assemblies)
{
// 获取全局映射配置
var config = TypeAdapterConfig.GlobalSettings;
// 扫描所有继承 IRegister 接口的对象映射配置
if (assemblies != null && assemblies.Length > 0) config.Scan(assemblies);
// 配置默认全局映射(支持覆盖)
config.Default
.NameMatchingStrategy(NameMatchingStrategy.Flexible)
.PreserveReference(true);
// 配置默认全局映射(忽略大小写敏感)
config.Default
.NameMatchingStrategy(NameMatchingStrategy.IgnoreCase)
.PreserveReference(true);
// 配置支持依赖注入
services.AddSingleton(config);
return services;
}
}
3. 自定义
- 自定义配置项
- 需要 实现
IRegister
( 因为配置文件 会自动检索程序集 找出有实现这个接口的类 )- 所以可以针对不同的类需求 创建多个自定义文件 都实现
IRegister
接口使用
- 所以可以针对不同的类需求 创建多个自定义文件 都实现
- 简单映射配置,命名不同一一对应
- 复杂映射配置,对应的属性做了一些操作
- 需要 实现
namespace DougWebApi.Common.Mapster;
public class MyTypeAdapterConfig : IRegister
{
public void Register(TypeAdapterConfig config)
{
// 简单映射
config.ForType<User, UserDto>().Map(dest => dest.NickName, src => src.Name);
// 复杂映射
config.ForType<Employee, EmployeeDto>()
.Map(dest => dest.Name,
src => $"{src.FirstName}{src.LastName}")
.Map(dest => dest.GenderDisplay, src => src.Gender.ToString())
.Map(dest => dest.Age, src => DateTime.Now.Year - src.DateOfBirth.Year);
}
}
4. Program
注册
// 捕获当前运行时的程序集 (不会捕获其他的类库,只有主项目)
builder.Services.AddMapsterIRegister(Assembly.GetExecutingAssembly());
// 或者使用 : (得到所有已加载的程序集,而不仅仅是当前的程序集)
builder.Services.AddMapsterIRegister(AppDomain.CurrentDomain.GetAssemblies());
// 再或者 加载 单个指定的程序集(自定义配置项文件存在的类库项目的程序集加载)
// MyTypeAdapterConfig : IRegister 扫描接口
builder.Services.AddMapsterIRegister(Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, "XX.Common.dll")));
使用
var 目标 = 来源.Adapt<目标>();
总结
推荐使用 Mapster
导入组件使用 基本都是 四步骤(or 三步骤肯定 :
- 依赖
- 配置组件
- 自定义文件( 这条有的组件不用
- 注册