C# Mapster 对象映射器(C#对象映射器)

您所在的位置:网站首页 冰封王座官方自带的防守地图 C# Mapster 对象映射器(C#对象映射器)

C# Mapster 对象映射器(C#对象映射器)

2024-01-05 23:23| 来源: 网络整理| 查看: 265

前言

谈到对象映射器,AutoMapper 知名度是非常的高,但很少有人知道 Mapster。而为什么选择 Mapster 呢?

理由一:性能优于 AutoMapper ,相关测试位于https://github.com/MapsterMapper/Mapster上查看。

理由二:多学习一项技能

网上查了一下,关于 Mapster 的资料非常少,所以在这里我们详细写下它的用法,以帮助更多的序员宝快速掌握它的用法。

官方文档:https://github.com/MapsterMapper/Mapster/wiki

安装 Mapster

PM> Install-Package Mapster 或者 dotnet add package Mapster

定义实体

目的:使用 Mapster 实现 User 到 UserDto 的映射

public class User { public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } public string like { get; set; } } public class UserDto { public string name { get; set; } public int UserAge { get; set; } public string UserSex { get; set; } public string like { get; set; } } 简单使用 /* * 默认情况下,无需任何配置,Mapster会根据两个实体字段名称相同进行匹配 * 第一次调用时,配置会被缓存,第二次将会从缓存中取,以此提升性能 */ var user = new User(); var dto = user.Adapt();//映射为新对象 user.Adapt(dto);//在目标对象的基础上进行映射 //注意:Adapt扩展方法使用的配置为 `TypeAdapterConfig.GlobalSettings` Mapster 配置 (TypeAdapterConfig)

可以直接使用 Mapster 内置的全局静态配置 TypeAdapterConfig.GlobalSettings,也可以实例化一个配置 new TypeAdapterConfig()

推荐使用实例化的方式,对 TypeAdapterConfig 进行映射配置。

注:Mapster 默认匹配规则是相同字段名之间进行映射。

方式一

直接在 TypeAdapterConfig 配置对象的映射关系

var config = new TypeAdapterConfig(); //映射规则 config.ForType() .Map(dest => dest.UserAge, src => src.Age) .Map(dest => dest.UserSex, src => src.Sex); var mapper = new Mapper(config);//务必将mapper设为单实例 var user = new User{Name = "xiaowang",Age = 18,Sex = "boy"}; var dto = mapper.Map(user);

字段带有前后缀,可以使用 NameMatchingStrategy.ConvertDestinationMemberName 对目标字段名称进行替换,使得它和源字段名称相同。 还有替换源字段的方法NameMatchingStrategy.ConvertSourceMemberName

注意:如果一个ForType定义多个NameMatchingStrategy,后定义的会覆盖先定义的规则,所以只有最后定义的规则会生效

var config = new TypeAdapterConfig(); //使用 config.ForType() .NameMatchingStrategy(NameMatchingStrategy.ConvertDestinationMemberName(dest => dest.Replace("User", ""))); 方式二

使用接口的方式,需要实现 IRegister

//实现接口 IRegister public class UserDtoRegister : IRegister { public void Register(TypeAdapterConfig config) { config.ForType() Map(dest => dest.UserAge, src => src.Age); //... } } //实例化Mapper var config = new TypeAdapterConfig(); //var config = TypeAdapterConfig.GlobalSettings; //只有要给定 IRegister 所在的程序集名称,Mapster 会自动识别 IRegister,进行配置注入。 config.Scan("程序集名称1","程序集名称2"); var mapper = new Mapper(config);//务必设置为单实例 忽略字段 var config = new TypeAdapterConfig(); //映射规则 config.ForType() .Map(dest => dest.UserAge, src => src.Age) .Map(dest => dest.UserSex, src => src.Sex); .IgnoreNullValues(true)//忽略空值映射 .Ignore(dest => dest.UserAge)//忽略指定字段 .IgnoreAttribute(typeof(DataMemberAttribute))//忽略指定特性的字段 .NameMatchingStrategy(NameMatchingStrategy.IgnoreCase)//忽略字段名称的大小写 .IgnoreNonMapped(true);//忽略除以上配置的所有字段 config.ForType() .IgnoreMember((member, side) => !member.Type.Namespace.StartsWith("System"));//实现更细致的忽略规则

member和side分别对应IMemberModel和MemberSide,这里我贴出相应的源码。

//包含了映射类型的信息 public interface IMemberModel { Type Type { get; } string Name { get; } object? Info { get; } AccessModifier SetterModifier { get; } AccessModifier AccessModifier { get; } IEnumerable GetCustomAttributes(bool inherit); } //标识当前是源类型还是目标类型 public enum MemberSide { Source = 0, Destination = 1 } 分支(Fork)

Mapster 的 Fork 功能允许我们定义局部的映射规则,并且分支不会重复编译,不需要考虑性能问题。

var config = new TypeAdapterConfig(); var mapper = new Mapper(config); var user = new User{Name = "xiaowang",Age = 18,Sex = "boy"}; var dto = mapper.From(user).ForkConfig(forked => { //该分支规则,不会重复编译,仅限该语句中有效,不会影响config的配置 forked.ForType().Map(dest => dest.name, src => src.Name); }) .AdaptToType();//映射为新对象 dto = mapper.From(user).ForkConfig(forked => { forked.ForType().Map(dest => dest.name, src => src.Name); }) .AdaptTo(new UserDto());//在目标对象基础上进行映射 NewConfig 方法

NewConfig 方法允许我们对两个类型之间新建配置,如果两个类型之前配置了映射关系,则 NewConfig 方法会覆盖之前的配置

var config = new TypeAdapterConfig(); config.ForType().Map(dest => dest.UserAge, src => src.Age); //... //覆盖 User 和 UserDto 之前的配置 config.NewConfig().Map(dest=>dest.UserAge,src=>100); //扩展知识:覆盖Mapster默认静态配置 TypeAdapterConfig.NewConfig().Default.NameMatchingStrategy(NameMatchingStrategy.IgnoreCase); 运行时传参

允许运行时传入数据,干预映射过程

var config = new TypeAdapterConfig(); config.ForType() .Map(dest => dest.name, src => MapContext.Current.Parameters["userName"]);//配置运行时参数 var mapper = new Mapper(config); //使用时传入数据 var user = new User(); var dto = mapper.From(user).BuildAdapter().AddParameters("userName","xiaowang").AdaptToType(); 其他知识点

我们尽量不要把实体间的映射规则配置到 TypeAdapterConfig.GlobalSettings (默认配置)。随着业务的发展,一个配置很难兼顾所有业务,可能会出行冲突的情况,相对复杂的业务,可以新建一个TypeAdapterConfig,或者使用 config.Clone()能轻松复制一份配置。全局配置可以放一些简单的配置项,例如:映射时忽略大小写。

注意:Adapt 扩展方法使用的是 TypeAdapterConfig.GlobalSettings

小技巧 Adapt 扩展方法的使用 Dictionary dict = new User().Adapt();//object 到 Dictionary 的转换 string s = 123.Adapt(); //equal to 123.ToString(); int i = "123".Adapt(); //equal to int.Parse("123"); 拦截映射前后

BeforeMapping 方法和 AfterMapping

//BeforeMapping 映射执行前 config.ForType().BeforeMapping((src, dest) => { src.Age = 100; dest.UserAge = src.Age + 10; }); //AfterMapping 映射执行后 //...

更多的使用技巧可以查看官方文档:https://github.com/MapsterMapper/Mapster/wiki



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3