当前位置: 首页 > news >正文

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

image

前言

在日常开发中,我们常常需要将一个对象映射到另一个对象,比如将数据库实体转换为数据传输对象(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

image

安装 Mapster 相关包

方式一、NuGet 包管理器安装

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

Mapster 核心功能包

image

Mapster.DependencyInjection 依赖注入集成包

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

映射结果输出:

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

映射结果输出:

image

完整示例源代码

  • https://github.com/YSGStudyHards/EasySQLite

image

http://www.hskmm.com/?act=detail&tid=35521

相关文章:

  • 列出 Redux 的组件?
  • 2025 年房屋鉴定公司最新推荐权威排行榜:涵盖安全评估 / 承载力 / 工程质量 / 危房等多领域,精准指引选靠谱机构
  • 放大器保护机制的技术原理与实现策略
  • 2025 年最新推荐!国内优质球墨铸铁管厂家排行榜出炉,涵盖自来水 / 给水 / 排污 / 污水用 / 消防 / 饮用水场景适用品牌
  • 2025 年球墨铸铁管件厂家最新推荐排行榜:市政 / 给排水 / 污水处理用优质厂家权威甄选
  • 2025 年最新防火涂料厂家排行榜:膨胀型 / 非膨胀型 / 厚型 / 薄型钢结构防火涂料优质企业最新推荐
  • 2025年GEO品牌推荐榜单:AI技术驱动的行业革新者
  • 2025年GEO品牌推荐排行榜TOP10:AI技术驱动的行业新格局
  • 2025 年南昌装修设计公司推荐:宿然设计,非营销型技术工作室,专注落地还原,提供全国纯设计与江西全案服务
  • 2025 年板材源头厂家最新推荐排行榜:聚焦 ENF 级环保与高品质,精选 6 家实力企业助您轻松选
  • 中部地区-河南湖北湖南
  • Hash与布隆过滤器
  • 2025 年最新推荐防火涂料厂家排行榜:涵盖膨胀型、非膨胀型、室内外及超薄厚型钢结构防火涂料,助选优质产品
  • 2025年安恒信息公司:深度解析AI与数据安全双轮驱动的技术护城河
  • C# Avalonia 16- Animation- SampleViewer - SimpleExample
  • 2025年安恒信息深度解析:AI与数据安全双轮驱动的技术演进全景
  • 习题-归纳定义原理
  • 对话式 AI 年度春晚:Convo AIRTE2025 全议程解锁
  • 博客的加载速度和大小的优化、优化再优化
  • 2025年10月中国宝宝辅食品牌推荐榜:深海去刺鱼领衔对比
  • 《51测试天地》电子杂志 第八十六期发布文章:打造基于 WebSocket + CDP 的 Selenium 替代方案
  • 实用指南:数字孪生背后的大数据技术:时序数据库为何是关键?
  • Qt和ffmpeg结合打造gb28181推流/支持udp和tcp被动以及tcp主动三种方式
  • 【每日积累】浅谈mvc,mvvm,mvp
  • Random VIMs
  • 66页习题
  • 【React系列】一文让你了解React中Component和PureComponent差异之分
  • DIY ChatGPT 一周狂揽 27k Star「GitHub 热点速览」
  • Active Directory安全技巧:FSMO角色管理与PowerShell查询
  • 【React系列】React.memo() vs useMemo()