在现代 .NET 应用中,经常会有不同层之间的数据传递需求:比如实体模型(Entity)到 DTO、DTO 到 ViewModel,或者响应模型到输入模型等。手写映射代码容易出错且维护成本高。Mapster 是一个优秀的对象映射库,它在性能、灵活性、易用性等多个方面表现突出。下面将介绍 Mapster 是什么、为什么选它、如何安装与使用,并通过一些进阶示例展示其强大能力。
什么是 Mapster?
Mapster 是一个开源的 .NET 对象映射库,专注于高性能和灵活性。它支持静态配置与动态映射、源生成(code generation)、LINQ 投影、深度映射、扁平化属性映射等功能。与 AutoMapper 等传统映射工具相比,其运行速度更快、开销更低。它在默认情况下按照属性(字段)名称相同原则自动映射,也支持各种自定义规则。
为什么选择 Mapster?
- 性能更优:Mapster 可以在运行时用表达式树或在编译时用源生成器生成映射代码,避免反射带来的性能开销。
- 轻量与灵活:不强制继承某类或标注特性即可使用。默认自动映射同名属性,也提供丰富 API 做自定义映射规则。
- 丰富特性支持:嵌套属性映射、集合映射、枚举 / 类型转换、扁平化 /扁平结构支持、条件映射、忽略空值 / 忽略特定属性映射等。
- 易集成:可以与依赖注入(DI)集成、项目中的映射配置模块化、支持全局或局部设定、支持源生成等特性使得在大型项目中维护映射规则更加简单。
安装与基础用法
下面是一个把 Mapster 引入到 .NET / C# 项目中的简单流程和基础示例。
1. 安装
在你的项目中通过 NuGet 安装 Mapster 包即可。命令类似:
Install-Package Mapster
或者使用 .NET CLI:
dotnet add package Mapster
如果需要源生成器或高级功能,可以额外安装相关包。
2. 基本映射示例
在安装好包之后,可以按以下方式创建实体类与 DTO,然后做基本映射。
using Mapster;
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
public class UserDto
{
public int Id { get; set; }
public string GivenName { get; set; }
public string FamilyName { get; set; }
}
// 在程序某处
var user = new User
{
Id = 1,
FirstName = "Alice",
LastName = "Smith",
Email = "alice@example.com"
};
// 简单映射:默认按属性名匹配,没有匹配的属性保持默认值
var dto = user.Adapt<UserDto>();
Console.WriteLine($"Id={dto.Id}, GivenName={dto.GivenName}, FamilyName={dto.FamilyName}");
3. 自定义规则
如果源与目标属性名称不一致,或者需要组合/转换,可以通过配置映射规则:
TypeAdapterConfig<User, UserDto>.NewConfig()
.Map(dest => dest.GivenName, src => src.FirstName)
.Map(dest => dest.FamilyName, src => src.LastName)
.Map(dest => dest.FamilyName, src => src.LastName.ToUpper()); // 示例:转换大小写
也可以设置全局匹配策略,例如忽略大小写、扁平结构等。
进阶用法
Mapster 提供许多进阶能力,在业务中常见场景非常实用:
- 集合与嵌套映射:映射列表、数组、子对象等结构,无需手动循环。例如 Adapt<List<Destination>>(sourceList) 支持深度嵌套对象映射。
- 条件映射 & 空值忽略:有些属性仅在某些条件下映射或仅在源值非空时映射。配置 MapIf(...) 或 IgnoreNullValues(...) 等机制。
- 扁平化映射(Flattening):将嵌套对象的子属性映射到目标对象的扁平字段,例如 Address.City → Address_City。这在某些 ViewModel 或导出格式中非常有用。
- 源生成器支持:Mapster 支持用源生成器(Source Generator)在编译时生成映射代码,这能避免运行时反射或表达式树带来的延迟。适合追求极致性能的场景。
- 集成在 ASP.NET Core 或 Dependency Injection 环境中:将映射配置封装为注册类(实现 IRegister 接口),在启动时扫描配置并通过 DI 提供映射器实例使用。这样结构清晰,维护控制更好。
Mapster vs AutoMapper 简要对比
为了帮助你权衡是否使用 Mapster,这里简单列几个与 AutoMapper 相比的优劣点:
- 速度与开销:Mapster 在很多测试中速度更快、内存开销更低。
- 配置倾向:AutoMapper 常依赖于配置 Profile,较多约定;Mapster 支持约定也支持灵活配置,对轻量快速场景更友好。
- 学习曲线:AutoMapper 社区成熟、文档多;Mapster 新特性多、灵活性高,但掌握其所有特性需要一些学习。
- 源码/编译时生成:Mapster 的源生成器能力在新 .NET 版本中是一个亮点,对于性能敏感、映射密集的系统尤为有用。
使用建议与最佳实践
为了让 Mapster 在项目中表现良好并易于维护,可以考虑以下建议:
- 尽量使用单例或全局配置(TypeAdapterConfig)管理映射规则,避免在每次映射时重复创建配置。
- 对于简单 DTO / ViewModel → 实体的映射,优先使用约定默认映射,减少重复配置。
- 对于复杂或性能关键的映射路径(嵌套、大集合/频繁调用处),考虑使用源生成器 /预先编译映射代码,以降低运行时开销。
- 保持映射规则清晰,给每个类型映射配置独立类(实现 IRegister 接口)或在特定模块中管理,便于维护与测试。
- 写单元测试验证映射规则(例如确认某个属性是否正确映射/忽略)。这样变更模型结构时能快速发现问题。
结语
Mapster 是一个功能强大、性能优异、灵活轻量的 .NET / C# 对象映射库。无论你是构建 API、微服务、前后端分层架构还是需要大量 DTO/ViewModel 转换的系统,Mapster 都是一个值得考虑的工具。通过本文的基础与进阶示例,你应该能够快速上手并将其融入自己的项目中。