前言
在日常开发中,我们常常需要将一个对象映射到另一个对象,比如将数据库实体转换为数据传输对象(DTO),或将请求模型映射为领域模型。这个过程通常涉及大量重复性代码,如果每次都手动编写,不仅严重影响开发效率,而且随着项目规模不断增长,还容易出现错误(如:属性遗漏、手写时写错或复制粘贴失误等)。
本文我们的主要内容就是讲解如何在 ASP.NET Core 9.0 Web API 项目中使用 Mapster 快速、高效的实现对象映射。
Mapster 介绍
Mapster 是一个开源免费(MIT license)、快速、高性能、灵活且易于使用的 .NET 对象映射库,用于在 .NET 用程序中进行对象之间的转换和映射操作,大幅减少手动赋值带来的重复代码、人为错误和维护成本。
- 开源地址:https://github.com/MapsterMapper/Mapster
- 在线文档:https://github.com/MapsterMapper/Mapster/wiki
安装 Mapster 相关包
方式一、NuGet 包管理器安装
在 NuGet 包管理器中搜索:Mapster 和 Mapster.DependencyInjection 安装:
Mapster 核心功能包
Mapster.DependencyInjection 依赖注入集成包
方式二、.NET CLI 安装
- dotnet add package Mapster --version 7.4.0 #核心功能包
- dotnet add package Mapster.DependencyInjection --version 1.0.1 #依赖注入集成包
复制代码 在 Program.cs 中注册 Mapster 服务
- var builder = WebApplication.CreateBuilder(args);
- // 注册 Mapster 服务
- builder.Services.AddMapster();
- // 注册 Mapster 映射规则
- MapsterConfig.Register();
复制代码 基础映射一行代码搞定
接下来我们分别定义一个源对象(Student)和一个目标对象(StudentViewModel),它们的属性名和类型完全一致。
Student(源对象)
- public classStudent
- {
- /// <summary>
- /// 学生ID [主键,自动递增]
- /// </summary>
- [PrimaryKey, AutoIncrement]
- [Display(Name = "学生ID")]
- publicint StudentID { get; set; }
- /// <summary>
- /// 班级ID
- /// </summary>
- [Display(Name = "班级ID")]
- publicint ClassID { get; set; }
- /// <summary>
- /// 学生姓名
- /// </summary>
- [Display(Name = "学生姓名")]
- publicstring Name { get; set; }
- /// <summary>
- /// 学生年龄
- /// </summary>
- [Display(Name = "学生年龄")]
- publicint Age { get; set; }
- /// <summary>
- /// 学生性别
- /// </summary>
- [Display(Name = "学生性别")]
- publicstring Gender { get; set; }
- }
复制代码 StudentViewModel(目标对象)
- public classStudentViewModel
- {
- /// <summary>
- /// 学生ID
- /// </summary>
- [PrimaryKey, AutoIncrement]
- [Display(Name = "学生ID")]
- publicint StudentID { get; set; }
- /// <summary>
- /// 班级ID
- /// </summary>
- [Display(Name = "班级ID")]
- publicint ClassID { get; set; }
- /// <summary>
- /// 学生姓名
- /// </summary>
- [Display(Name = "学生姓名")]
- publicstring Name { get; set; }
- /// <summary>
- /// 学生年龄
- /// </summary>
- [Display(Name = "学生年龄")]
- publicint Age { get; set; }
- /// <summary>
- /// 学生性别
- /// </summary>
- [Display(Name = "学生性别")]
- publicstring Gender { get; set; }
- /// <summary>
- /// 班级名称
- /// </summary>
- [Display(Name = "班级名称")]
- publicstring ClassName { get; set; }
- }
复制代码 Mapster 自动完成映射
只要属性名和类型一致,Mapster 自动完成映射,无需任何配置!- private async Task<List<StudentViewModel>?> GetStudentClassInfo(List<Student> students)
- {
- // Mapster 映射(无需任何配置!)
- var studentsListDto = students.Adapt<List<StudentViewModel>>();
- if (studentsListDto?.Count > 0)
- {
- var classIDs = studentsListDto.Select(x => x.ClassID).Distinct().ToList();
- var querySchoolClassList = await _schoolClassHelper.QueryAsync(x => classIDs.Contains(x.ClassID)).ConfigureAwait(false);
- if (querySchoolClassList?.Count > 0)
- {
- foreach (var studentItem in studentsListDto)
- {
- var getClassInfo = querySchoolClassList.FirstOrDefault(x => x.ClassID == studentItem.ClassID);
- if (getClassInfo != null)
- {
- studentItem.ClassName = getClassInfo.ClassName;
- }
- }
- }
- }
- return studentsListDto;
- }
复制代码 映射结果输出:
自定义映射规则
当属性名或类型不一致时,可通过配置指定映射逻辑。
UserInfo(源对象)
- public classUserInfo
- {
- publicint Id { get; set; }
- publicstring FirstName { get; set; }
- publicstring LastName { get; set; }
- publicstring Email { get; set; }
- public DateTime CreatedAt { get; set; }
- }
复制代码 UserInfoViewModel(目标对象)
- public classUserInfoViewModel
- {
- publicint Id { get; set; }
- /// <summary>
- /// 合并 FirstName + LastName
- /// </summary>
- publicstring FullName { get; set; }
- publicstring Email { get; set; }
- /// <summary>
- /// 格式化日期
- /// </summary>
- publicstring CreatedDate { get; set; }
- }
复制代码 配置 Mapster 映射规则
在项目根目录创建 MapsterConfig.cs:- /// <summary>
- /// Mapster 全局映射配置类。
- /// 用于集中注册项目中所有自定义的对象映射规则,
- /// 避免映射逻辑分散在各处,提升可维护性与可测试性。
- /// </summary>
- publicstaticclassMapsterConfig
- {
- /// <summary>
- /// 注册所有自定义的 Mapster 映射配置
- /// 此方法应在应用程序启动时(如 Program.cs)调用一次
- /// </summary>
- public static void Register()
- {
- TypeAdapterConfig<UserInfo, UserInfoViewModel>
- .NewConfig()
- .Map(dest => dest.FullName,
- src => $"{src.FirstName} {src.LastName}".Trim())
- .Map(dest => dest.CreatedDate,
- src => src.CreatedAt.ToString("yyyy-MM-dd"));
- }
- }
复制代码 自定义映射规则
- /// <summary>
- /// 使用 Mapster 映射 UserInfo 示例
- /// </summary>
- [ApiController]
- [Route("api/[controller]/[action]")]
- publicclassUserInfoController : ControllerBase
- {
- privatereadonly IMapper _mapper;
- /// <summary>
- /// 依赖注入
- /// </summary>
- /// <param name="mapper">mapper</param>
- public UserInfoController(IMapper mapper)
- {
- _mapper = mapper;
- }
- /// <summary>
- /// GetUserInfo
- /// </summary>
- /// <returns></returns>
- [HttpGet]
- public List<UserInfoViewModel> GetUserInfos()
- {
- var userInfos = new List<UserInfo>
- {
- new UserInfo
- {
- Id = 999,
- FirstName = "李",
- LastName = "四",
- Email = "lisi@qq.com",
- CreatedAt = DateTime.Now.AddYears(-5)
- },
- new UserInfo
- {
- Id = 666,
- FirstName = "张",
- LastName = "三",
- Email = "zhangsan@example.com",
- CreatedAt = DateTime.UtcNow.AddDays(-10)
- }
- };
- // 使用 Mapster 映射
- var getUserInfoViewModels = _mapper.Map<List<UserInfoViewModel>>(userInfos);
- return getUserInfoViewModels;
- }
- }
复制代码 映射结果输出:
完整示例源代码
- https://github.com/YSGStudyHards/EasySQLite
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |