当前位置:网站首页> 4. 对象映射 - Mapping.Mapster
4. 对象映射 - Mapping.Mapster
2022-07-05 06:10:00 【MASA技术团队】
前言
在项目中我们会经常遇到对象的映射,比如像Model和Dto之间的映射,或者是对象的深拷贝,这些都是需要我们自己实现的。此时,项目中会出现很多初始化对象的代码,这些代码写起来相当的枯燥乏味,那么有没有什么办法减轻我们的工作量,使得我们可以把时间花费到业务功能上呢?
目前,.Net中的对象映射框架,功能强大且性能极佳的对象映射框架已经存在,其中使用最多的有:
说到对象映射框架,大家想到的最多的是AutoMapper,可能很多人连Mapster都没听过,但不可否认的是Mapster确实是一个很好的对象映射框架,但由于中文文档的缺失,导致在国内知名度不是很高,今天我们就来介绍一下Mapster提供了哪些功能,如何在项目中使用它,Masa提供的Mapster又做了什么?
Mapster 简介
Mapster是一个使用简单,功能强大的对象映射框架,自2014年开源到现在已经过去8个年头,截止到现在,github上已经拥有2.6k的star,并保持着每年3次的发版频率,其功能与AutoMapper类似,提供对象到对象的映射、并支持IQueryable到对象的映射,与AutoMapper相比,在速度和内存占用方面表现的更加优秀,可以在只使用1/3内存的情况下获得4倍的性能提升,那我们下面就来看看Mapster如何使用?
准备工作
新建一个控制台项目
Assignment.Mapster,并安装Mapsterdotnet add package Mapster --version 7.3.0
映射到新对象
新建类
UserDtopublic class UserDto{ public int Id { get; set; } public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; }}新建一个匿名对象,作为待转换的对象源
var user = new{ Id = 1, Name = "Tom", Gender = 1, BirthDay = DateTime.Parse("2002-01-01")};将user源对象映射到为目标对象 (UserDto)
var userDto = user.Adapt<UserDto>();Console.WriteLine($"映射到新对象,Name: {userDto.Name}");
运行控制台程序验证转换成功: 
数据类型
除了提供对象到对象的映射,还支持数据类型的转换,如:
基本类型
提供类型映射的功能,类似Convert.ChangeType()
string res = "123";decimal i = res.Adapt<decimal>(); //equal to (decimal)123;Console.WriteLine($"结果为:{i == int.Parse(res)}");
运行控制台程序: 
枚举类型
把枚举映射到数字类型,同样也支持字符串到枚举和枚举到字符串的映射,比.NET的默认实现快两倍
var fileMode = "Create, Open".Adapt<FileMode>();//等于 FileMode.Create | FileMode.OpenConsole.WriteLine($"枚举类型转换的结果为:{fileMode == (FileMode.Create | FileMode.Open)}");
运行控制台程序验证转换成功: 
Queryable扩展
Mapster提供了Queryable的扩展,用于实现DbContext的按需查找,例如:
新建类
UserDbContextusing Assignment.Mapster.Domain;using Microsoft.EntityFrameworkCore;namespace Assignment.Mapster.Infrastructure;public class UserDbContext : DbContext{ public DbSet<User> User { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { var dataBaseName = Guid.NewGuid().ToString(); optionsBuilder.UseInMemoryDatabase(dataBaseName);//使用内存数据库,方便测试 }}新建类
Userpublic class User{ public int Id { get; set; } public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; } public DateTime CreationTime { get; set; } public User() { CreationTime = DateTime.Now; }}使用基于Queryable的扩展方法
ProjectToTypeusing (var dbContext = new UserDbContext()){ dbContext.Database.EnsureCreated(); dbContext.User.Add(new User() { Id = 1, Name = "Tom", Gender = 1, BirthDay = DateTime.Parse("2002-01-01") }); dbContext.SaveChanges(); var userItemList = dbContext.User.ProjectToType<UserDto>().ToList();}
运行控制台程序验证转换成功: 
除此之外,Mapster还提供了映射前/后处理,拷贝与合并以及映射配置嵌套支持,详细可查看文档,既然Mapster已经如此强大,那我直接使用它就可以了,为什么还要使用Masa提供的Mapper呢?
什么是Masa.Contrib.Data.Mapping.Mapster?
Masa.Contrib.Data.Mapping.Mapster是基于Mapster的一个对象到对象的映射器,并在原来Mapster的基础上增加自动获取并使用最佳构造函数映射,支持嵌套映射,减轻映射的工作量。
映射规则
目标对象没有构造函数时:使用空构造函数,映射到字段和属性。
目标对象存在多个构造函数:获取最佳构造函数映射
最佳构造函数: 目标对象构造函数参数数量从大到小降序查找,参数名称一致(不区分大小写)且参数类型与源对象属性一致
准备工作
新建一个控制台项目
Assignment.Masa.Mapster,并安装Masa.Contrib.Data.Mapping.Mapster,Microsoft.Extensions.DependencyInjectiondotnet add package Masa.Contrib.Data.Mapping.Mapster --version 0.4.0-rc.4dotnet add package Microsoft.Extensions.DependencyInjection --version 6.0.0
新建类
OrderItempublic class OrderItem{ public string Name { get; set; } public decimal Price { get; set; } public int Number { get; set; } public OrderItem(string name, decimal price) : this(name, price, 1) { } public OrderItem(string name, decimal price, int number) { Name = name; Price = price; Number = number; }}新建类
Orderpublic class Order{ public string Name { get; set; } public decimal TotalPrice { get; set; } public List<OrderItem> OrderItems { get; set; } public Order(string name) { Name = name; } public Order(string name, OrderItem orderItem) : this(name) { OrderItems = new List<OrderItem> { orderItem }; TotalPrice = OrderItems.Sum(item => item.Price * item.Number); }}修改类
Programusing Assignment.Masa.Mapster.Domain.Aggregate;using Masa.BuildingBlocks.Data.Mapping;using Masa.Contrib.Data.Mapping.Mapster;using Microsoft.Extensions.DependencyInjection;Console.WriteLine("Hello Masa Mapster!");IServiceCollection services = new ServiceCollection();services.AddMapping();var request = new{ Name = "Teach you to learn Dapr ……", OrderItem = new OrderItem("Teach you to learn Dapr hand by hand", 49.9m)};var serviceProvider = services.BuildServiceProvider();var mapper = serviceProvider.GetRequiredService<IMapper>();var order = mapper.Map<Order>(request);Console.WriteLine($"{nameof(Order.TotalPrice)} is {order.TotalPrice}");//控制台输出49.9Console.ReadKey();
如果转换成功,TotalPrice的值应该是49.9,那么我们运行控制台程序来验证转换是否成功:

如何实现
上面我们提到了Masa.Contrib.Data.Mapping.Mapster可以自动获取并使用最佳构造函数映射,进而完成对象到对象的映射,那么它是如何实现的呢?会不会对性能有什么影响呢?
做到自动获取并使用最佳构造函数映射是使用的Mapster提供的构造函数映射的功能,通过指定构造函数,完成对象到对象的映射。
查看文档
总结
目前Masa.Contrib.Data.Mapping.Mapster的功能相对较弱,当前版本与Mapster的相比仅仅增加了一个自动获取并使用最佳构造函数的功能,让我们在面对无空构造函数且拥有多个构造函数的类时也能轻松的完成映射,不需要额外多写一行代码。
但我觉得Masa版的Mapping最大的好处是项目依赖的是BuildingBlocks下的IMapper,而不是Mapster,这也就使得我们的项目与具体的映射器实现脱离,如果我们被要求项目必须要使用AutoMapper,只需要实现AutoMapper版的IMapper即可,无需更改太多的业务代码,仅需要更换一下引用的包即可,这也是BuildingBlocks的魅力所在
本章源码
Assignment04
https://github.com/zhenlei520/MasaFramework.Practice
开源地址
MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks
MASA.Contrib:https://github.com/masastack/MASA.Contrib
MASA.Utils:https://github.com/masastack/MASA.Utils
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们

边栏推荐
猜你喜欢

How to adjust bugs in general projects ----- take you through the whole process by hand

leetcode-6111:螺旋矩阵 IV

Analysis of backdoor vulnerability in remote code execution penetration test / / phpstudy of national game title of national secondary vocational network security B module

Erreur de connexion Navicat à la base de données Oracle Ora - 28547 ou Ora - 03135

中职网络安全技能竞赛——广西区赛中间件渗透测试教程文章

Spark中groupByKey() 和 reduceByKey() 和combineByKey()

Some common problems in the assessment of network engineers: WLAN, BGP, switch

Navicat連接Oracle數據庫報錯ORA-28547或ORA-03135

On the characteristics of technology entrepreneurs from Dijkstra's Turing Award speech

【Jailhouse 文章】Jailhouse Hypervisor
随机推荐
Introduction et expérience de wazuh open source host Security Solution
wordpress切换页面,域名变回了IP地址
2022年贵州省职业院校技能大赛中职组网络安全赛项规程
中职网络安全技能竞赛——广西区赛中间件渗透测试教程文章
【Rust 笔记】16-输入与输出(上)
Redis publish subscribe command line implementation
Smart construction site "hydropower energy consumption online monitoring system"
1040 Longest Symmetric String
R language [import and export of dataset]
Sqlmap tutorial (1)
One question per day 2047 Number of valid words in the sentence
网络工程师考核的一些常见的问题:WLAN、BGP、交换机
Navicat連接Oracle數據庫報錯ORA-28547或ORA-03135
Traditional databases are gradually "difficult to adapt", and cloud native databases stand out
shared_ Repeated release heap object of PTR hidden danger
Simply sort out the types of sockets
可变电阻器概述——结构、工作和不同应用
JS quickly converts JSON data into URL parameters
[jailhouse article] performance measurements for hypervisors on embedded ARM processors
Transform optimization problems into decision-making problems