在 .NET 9 中使用 Mapster 快速、高效的實現對象映射

前言
在日常開發中,我們常常需要將一個對象映射到另一個對象,比如將數據庫實體轉換為數據傳輸對象(DTO),或將請求模型映射為領域模型。這個過程通常涉及大量重復性代碼,如果每次都手動編寫,不僅嚴重影響開發效率,而且隨著項目規模不斷增長,還容易出現錯誤(如:屬性遺漏、手寫時寫錯或復制粘貼失誤等)。
本文我們的主要內容就是講解如何在 ASP.NET Core 9.0 Web API 項目中使用 Mapster 快速、高效的實現對象映射。
Mapster 介紹
Mapster 是一個開源免費(MIT license)、快速、高性能、靈活且易于使用的 .NET 對象映射庫,用于在 .NET 用程序中進行對象之間的轉換和映射操作,大幅減少手動賦值帶來的重復代碼、人為錯誤和維護成本。

安裝 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;
}
}
映射結果輸出:

完整示例源代碼

作者名稱:追逐時光者
作者簡介:一個熱愛編程、善于分享、喜歡學習、探索、嘗試新事物和新技術的全棧軟件工程師。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。如果該篇文章對您有幫助的話,可以點一下右下角的【♥推薦♥】,希望能夠持續的為大家帶來好的技術文章,文中可能存在描述不正確的地方,歡迎指正或補充,不勝感激。

浙公網安備 33010602011771號