在这篇文章中,我们看看C# .NET中的对象到对象的映射器。映射器解决了在对象之间赋值时编写平凡而重复的代码的常见问题。 我们评估了三个不同的映射库,以了解共同的主题和一些可能与你的开发需求有关的差异。
映射库AutoMapper、AgileMapper和Mapster已被用于一个简单的演示程序,以探索一些简单的映射场景。
如果这对你来说是一个新的领域,那么希望你能从阅读这篇文章中获得一些知识。 或者你已经使用同一个对象映射器有一段时间了;你是否应该考虑一个替代方案?
什么是对象映射器,它解决什么问题?
对象到对象的映射是将值从一个对象分配到另一个对象的过程。 这在分层架构中很常见,特别是那些使用ORM框架(如Entity Framework Core)开发的架构。 在应用程序代码中,可能有很多情况需要在底层实体模型类和数据传输对象(DTO)之间转换数据。 另一种情况是在DTO之间使用对象映射,通常是从Web API到MVC Web应用程序中的视图模型类。
映射代码的编写是相当平凡和重复的,一个很好的解决方案是使用映射库。 映射库通常通过匹配对象中的成员来工作,并通过使用一套基于名称的约定,在某些情况下也包括类型的对象图。
使用对象映射器的好处
用映射库解决对象到对象的映射问题将使你作为一个开发者的生活更轻松。下面是一些直接的好处。
- 不写重复的无聊代码
- 更小、更干净的代码库
- 在整个代码库中对属性进行一致的命名
- 这是一个被开发者很好地采纳的策略
比较对象映射库
在这篇文章中,对每个映射库进行了以下比较。
- 受欢迎程度
- 易用性
- 配置的方便性
- 收藏
- 映射和反向映射
- 扁平化和非扁平化
- 嵌套对象
- 投影
- 文档
在这次评估中,使用了一个C# .Net Core 5控制台应用程序,使用EntityFramework Core和SqlLite数据库。 它是一个分层架构的简化模型,可在GitHub上获得。
该项目包含一个简单的服务接口,提供了一些基本的测试场景,如单层对象到对象的映射、包含集合的对象的两层对象映射,以及反向映射。
在项目代码中,每个映射方案都实现了接口。 另外,为了慎重起见,该接口的实现没有使用映射器。这就是我们希望通过使用映射库来消除的那些平凡的代码!
映射可以变得相当深入,所以没有涵盖所有的用例,但这个简单的项目是可用的,并且可以进一步扩展以尝试不同的东西。
对象映射库
我们比较了三个对象映射库。有一系列的库可以使用,但这里我们有一个非常流行的、相当流行的和不太知名的对象映射库进行比较。
AutoMapper
这是我们目前选择的对象映射器。我们决定在最近的一些项目中使用AutoMapper,因为它已经很受欢迎,而且在Jon P Smith的实用书《Entity Framework Core in Action》中使用了它。
AutoMapper采用低配置的方法,被设计用于依赖性注入的场景,如ASP.Net Core应用程序中。
AutoMapper需要一个配置,该配置可以被划分为配置文件并进行验证。 该库可以执行扫描操作,以便在构建配置时包括所有配置文件。 它创建了一个表达式树,可以在调试期间使用视图的扩展进行检查。
AgileMapper
AgileMapper是一个零配置、高度可配置的对象-对象映射器,具有可查看的执行计划。
成员根据一组名称和类型规则进行匹配。 如果类型没有映射,不需要额外的配置来防止错误。
执行计划是通过创建表达式树并将其编译为一个函数而形成的,然后这些计划被缓存起来。 这些计划可以被预先缓存,也可以被查看。执行计划可以在开发过程中被验证。
该库还提供深度克隆、更新和合并等有用的功能。
参见https://github.com/agileobjects/AgileMapper
地图
Mapster是另一个零配置的对象-对象映射器,通过名字进行匹配。 再一次,它支持配置,配置可以被验证。
它使用一个扩展方法,在任何对象上都可以执行映射操作。 另一个扩展方法提供了一种方便的方式,在映射过程中在运行时传入值。
根据它自己的GitHub项目页面,Mapster拥有良好的性能,并与其他库进行了有利的比较。
代码库还提供了一个工具,用于从实体类中创建DTO类和扩展方法,可以生成代码并节省时间。
它们是如何比较的?
受欢迎程度
从目前的使用情况来看,AutoMapper是迄今为止所选的三个映射库中最受欢迎和最成熟的。
AgileMapper | AutoMapper | Mapster | |
NuGet版本 | 1.8.0 | 10.1.1 | 7.2.0 |
总下载量 | 300k | 150M | 2.3M |
日均下载量 | 100 | 39k | 1k |
GitHub之星 | 375 | 8k | 1.5k |
* 截至2021年5月17日正确
易用性
这三个库都很容易理解,并使用NuGet进行设置。 就可用性而言,Agile Mapper和Mapster比AutoMapper更容易,因为它们都没有配置的要求。
这三个库的入门都是类似的。
- 安装软件包
- 有要映射的源和目标类型
- 创建配置(AutoMapper需要)。
- 创建实例(AutoMapper 要求)。
- 执行一些映射!
Agile Mapper和Mapster都提供了一个静态API,这是AutoMapper在v9中删除的东西。
Mapster与其他两个略有不同,因为它为映射操作提供了一个扩展方法。这是一个方便的功能,使用起来感觉很自然。
配置的简易性
尽管按照惯例工作,但在大多数情况下需要进行映射配置。代码示例中包含的一个微不足道的例子是将一个源的名字和姓氏映射到一个目标的全名字段。 这是一个在所有三个中使用流畅的语法的直接练习。
所有的库都被设计成与依赖性注入一起工作,配置作为启动操作被创建一次。 这将为应用程序提供一套编译好的映射,从而提高性能。
配置可以很容易地加载,因为所有的库都提供了一种扫描配置类的方法,这在较大的代码库中特别有用。
AgileMapper提供了一些额外的扩展方法来限制何时应用,这是一个很好的功能,这三个库都支持映射发生前后的操作。
采集
AgileMapper似乎比AutoMapper或Mapster支持更多的集合类型。 AgileMapper和Mapster也都支持Dictionary,但只针对字符串类型的键。
在映射过程中,当没有值被映射时,AutoMapper和AgileMapper都初始化了空集合。 这种行为是很好的做法,因为集合被期望被初始化。Mapster没有这样做,而是将空值作为默认行为返回。
映射和逆向映射
所有三个库都基于匹配的名字进行直接映射,它们也进行反向映射,尽管AutoMapper需要配置才能工作。
另一个测试是看一个较大的类型映射到一个较小的类型时的默认行为,在这种情况下,int 到byte 。
这三个库都以不同的方式处理这种情况。
- AutoMapper抛出了一个运行时异常,所以这个映射必须被明确地忽略掉。
- AgileMapper忽略了这个映射,因为它有更复杂的映射规则。
- Mapster实际上执行了一个映射,并向目标成员添加了一个错误的值。使用配置忽略成员,这是很容易避免的。
和所有事情一样,测试和探索数据的实际情况并验证配置是至关重要的。
扁平化
当目标名称遵循一个简单的模式时,这三个系统都支持常规的扁平化,不需要任何特殊的配置。
例如:source.Author.StarRating 会映射到dest.AuthorStarRating.
嵌套对象
三者都支持映射一个对象图,无需任何额外的配置。 AgileMapper有一个专门的扁平化API,有一些有用的功能,如将一个对象扁平化为一个字典或查询字符串参数列表。
IQueryable 投影
这三家公司都支持IQueryable投影,这是一种方便的方式,当使用EF Core时,可以直接将一个实体对象映射到目标DTO上。
除了AutoMapper需要将配置传入扩展方法,它们都非常相似。
该投影确保在选择语句中只声明所需的成员。 该代码示例包括SQL日志,以便有可能检查生成的SQL。
文档
每个库都有文档,但AutoMapper和AgileMapper有最清晰和最全面的内容。 Mapster在这方面可以改进,但嘿,这是开源的!
关于性能的说明
本研究的目的不是做性能比较。 Mapster由于采用了预编译策略,所以与AutoMapper相比,拥有更高的性能。然而,所有的库都以类似的方式工作,使用已编译的表达式树,然后缓存起来供将来执行。
总结
首先,如果你正在编写手动对象到对象的映射代码,那么就开始使用映射库吧!这将加快你的开发速度,使你有更少的代码行需要维护。 有很多选择,但本文中的三个都是合适的人选。
如果你正在寻找一个快速的方法,那么在这三个中,AgileMapper给你一个不费力气、零配置的开始,你可以通过使用其静态API开始。
在看了AutoMapper、AgileMapper和Mapster之后,结论是它们都相当相似。 它们都包含了对象映射任务所需的关键功能。 在使用和配置上有细微的差别,但在大多数情况下任何一个都应该是好的。
AutoMapper的强制配置导致了预先定义配置的好习惯,但缺乏静态API,消除了其他两个库的一些多功能性。
Mapster的扩展方法方法是一种自然的映射对象的方式,他们的性能数据,如果是真的,是一种奖励,但在映射中存在一个问题,需要配置来解决。
AgileMapper似乎有一套很好的映射规则,有高质量的文档和一些其他库中没有的有用功能。
如前所述,在所有情况下,都要花时间验证和检查映射配置,并注意基于惯例的映射在某些情况下会导致数据错误。
这些库的功能很丰富,本文没有涵盖它们能做的所有事情。 如果你想了解更多,那么请阅读文档,并随时使用演示项目!
谢谢你阅读这篇关于对象映射库的简短比较。
主题。
c#, web开发, .net, 映射