在 .NET 9 中使用 Mapster 快速、高效的实现对象映射

大模型关系型数据库云安全

picture.image

picture.image

前言

在日常开发中,我们常常需要将一个对象映射到另一个对象,比如将数据库实体转换为数据传输对象(DTO),或将请求模型映射为领域模型。这个过程通常涉及大量重复性代码,如果每次都手动编写,不仅严重影响开发效率,而且随着项目规模不断增长,还容易出现错误(如:属性遗漏、手写时写错或复制粘贴失误等)。

本文我们的主要内容就是讲解如何在 ASP.NET Core 9.0 Web API 项目中使用 Mapster 快速、高效的实现对象映射。

DotNetGuide编程学院

DotNetGuide编程学院是一个专注于C#/.NET/.NET Core学习、工作、面试干货和实战教程分享的知识星球!当然这里不仅仅只有C#/.NET/.NET Core还有前端、云原生(Docker,K8s)、分布式,微服务、实用工具、学习书籍、AIGC、AI赋能、求职和招聘资讯、热点资讯等多个领域,我们致力于构建一个积极向上、和谐友善的.NET技术交流、学习平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

加入后如果感觉不值得,3天内在知识星球APP右上角点击退出星球,可直接全额退款,无任何套路!

picture.image

Mapster 介绍

Mapster 是一个开源免费(MIT license)、快速、高性能、灵活且易于使用的 .NET 对象映射库,用于在 .NET 用程序中进行对象之间的转换和映射操作,大幅减少手动赋值带来的重复代码、人为错误和维护成本。

picture.image

安装 Mapster 相关包

方式一、NuGet 包管理器安装

在 NuGet 包管理器中搜索:MapsterMapster.DependencyInjection 安装:

Mapster 核心功能包

picture.image

Mapster.DependencyInjection 依赖注入集成包

picture.image

方式二、.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;  
        }  

映射结果输出:

picture.image

自定义映射规则

当属性名或类型不一致时,可通过配置指定映射逻辑。

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;  
        }  
    }  

映射结果输出:

picture.image

完整示例源代码

picture.image

picture.image

picture.image

picture.image

学习是一个永无止境的过程,你知道的越多,你不知道的也会越多,在有限的时间内坚持每天多学一点,你一定能成为你想要成为的那个人。不积跬步无以至千里,不积小流无以成江海!

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
如何利用云原生构建 AIGC 业务基石
AIGC即AI Generated Content,是指利用人工智能技术来生成内容,AIGC也被认为是继UGC、PGC之后的新型内容生产方式,AI绘画、AI写作等都属于AIGC的分支。而 AIGC 业务的部署也面临着异构资源管理、机器学习流程管理等问题,本次分享将和大家分享如何使用云原生技术构建 AIGC 业务。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论