Mapster 高级功能解析:高效对象映射与优化技巧

news/2024/11/5 16:31:01/文章来源:https://www.cnblogs.com/forges/p/18528274

在现代开发中,对象之间的转换是常见且繁琐的任务,尤其是在多层架构或跨系统数据传输的场景下。Mapster 是一个轻量级、高性能的对象映射库,旨在简化这些任务。相比于其他映射工具,Mapster 以其简洁易用、灵活强大和高性能的特点在开发者中受到广泛欢迎。

本文将深入讲解 Mapster 的各种高级用法和应用场景,包括映射集合、嵌套对象、条件映射、自定义转换等,帮助你更高效地进行对象转换。


1. 安装和基本用法

首先,确保你已通过 NuGet 安装了 Mapster:

Install-Package Mapster

或者在 .NET 项目中使用以下命令:

dotnet add package Mapster

基本的对象映射

Mapster 的核心是 TypeAdapter 类,它提供了多种映射方法。最常用的方法是 Adapt(),它用于将一个对象映射到另一个对象。

using Mapster;
using System;

public class Source
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Destination
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Program
{
   public static void Main()
  {
       var source = new Source { Id = 1, Name = "Mapster" };
       
       // 映射
       var destination = source.Adapt<Destination>();
       
       Console.WriteLine($"Id: {destination.Id}, Name: {destination.Name}");
  }
}

2. 映射集合类型

Mapster 允许将集合类型(如 List、Array 等)进行映射。例如,将 List<Source> 映射为 List<Destination>,Mapster 会自动遍历集合并进行对象映射。

示例:映射 List 集合

using Mapster;
using System;
using System.Collections.Generic;

public class Source
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Destination
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Program
{
   public static void Main()
  {
       var sourceList = new List<Source>
      {
           new Source { Id = 1, Name = "Alice" },
           new Source { Id = 2, Name = "Bob" }
      };

       // 映射 List<Source> 到 List<Destination>
       var destinationList = sourceList.Adapt<List<Destination>>();

       foreach (var dest in destinationList)
      {
           Console.WriteLine($"Id: {dest.Id}, Name: {dest.Name}");
      }
  }
}

示例:映射 Array

public class Program
{
   public static void Main()
  {
       var sourceArray = new Source[]
      {
           new Source { Id = 1, Name = "John" },
           new Source { Id = 2, Name = "Jane" }
      };

       // 映射数组
       var destinationArray = sourceArray.Adapt<Destination[]>();

       foreach (var dest in destinationArray)
      {
           Console.WriteLine($"Id: {dest.Id}, Name: {dest.Name}");
      }
  }
}

3. 嵌套对象映射

Mapster 支持嵌套对象的自动映射。例如,一个对象包含另一个对象作为属性,Mapster 会递归地处理这些嵌套的对象。

示例:嵌套对象映射

public class Source
{
   public int Id { get; set; }
   public string Name { get; set; }
   public Address Address { get; set; }
}

public class Address
{
   public string Street { get; set; }
   public string City { get; set; }
}

public class Destination
{
   public int Id { get; set; }
   public string Name { get; set; }
   public AddressDto Address { get; set; }
}

public class AddressDto
{
   public string Street { get; set; }
   public string City { get; set; }
}

public class Program
{
   public static void Main()
  {
       var source = new Source
      {
           Id = 1,
           Name = "Alice",
           Address = new Address
          {
               Street = "123 Elm Street",
               City = "Wonderland"
          }
      };

       // 自动映射嵌套对象
       var destination = source.Adapt<Destination>();

       Console.WriteLine($"Id: {destination.Id}, Name: {destination.Name}");
       Console.WriteLine($"Street: {destination.Address.Street}, City: {destination.Address.City}");
  }
}

4. 条件映射

Mapster 允许根据条件进行映射。例如,我们可以根据源对象的属性值来决定目标属性的映射值。

示例:条件映射

public class Source
{
   public int Age { get; set; }
}

public class Destination
{
   public string AgeCategory { get; set; }
}

public class Program
{
   public static void Main()
  {
       var source = new Source { Age = 25 };

       // 根据条件映射
       var destination = source.Adapt<Destination>(config =>
           config.Map(dest => dest.AgeCategory, src => src.Age >= 18 ? "Adult" : "Minor")
      );

       Console.WriteLine($"Age Category: {destination.AgeCategory}");
  }
}

在这个例子中,AgeCategory 的值是根据 Age 的值进行映射的。如果 Age 大于等于 18,则映射为 "Adult",否则映射为 "Minor"

示例:使用条件进行自定义映射

public class Source
{
   public bool IsActive { get; set; }
}

public class Destination
{
   public string Status { get; set; }
}

public class Program
{
   public static void Main()
  {
       var source = new Source { IsActive = true };

       // 使用条件进行自定义映射
       var destination = source.Adapt<Destination>(config =>
           config.Map(dest => dest.Status, src => src.IsActive ? "Active" : "Inactive")
      );

       Console.WriteLine($"Status: {destination.Status}");
  }
}

5. 自定义转换逻辑

有时我们需要进行自定义的映射操作,比如根据某个字段进行处理。Mapster 提供了 config.Map() 方法来实现这些自定义转换。

示例:自定义转换函数

public class Source
{
   public string FullName { get; set; }
}

public class Destination
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

public class Program
{
   public static void Main()
  {
       var source = new Source { FullName = "John Doe" };

       // 自定义转换逻辑,将 FullName 拆分为 FirstName 和 LastName
       var destination = source.Adapt<Destination>(config =>
           config.Map(dest => dest.FirstName, src => src.FullName.Split(' ')[0])
                .Map(dest => dest.LastName, src => src.FullName.Split(' ')[1])
      );

       Console.WriteLine($"First Name: {destination.FirstName}, Last Name: {destination.LastName}");
  }
}

在这个例子中,FullName 被拆分为 FirstNameLastName。通过自定义转换函数,你可以在映射过程中进行更多的数据处理。

6. 高级功能

Mapster 除了提供基础的对象映射功能,还支持多种高级特性,帮助开发者在不同的应用场景中更高效地进行对象映射,提升性能和灵活性。以下是一些 Mapster 的高级功能:

1. 映射配置

在使用 Mapster 时,我们通常会对多个不同的类进行映射。如果每次映射时都要配置相同的映射规则,就显得冗余且容易出错。Mapster 提供了全局映射配置的功能,允许你预先定义映射规则,避免重复配置。

示例:全局映射配置
using Mapster;
using System;

public class Source
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Destination
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Program
{
   public static void Main()
  {
       // 全局配置映射规则
       TypeAdapterConfig<Source, Destination>.NewConfig()
          .Map(dest => dest.Name, src => src.Name.ToUpper());  // 把 Name 字段转为大写

       var source = new Source { Id = 1, Name = "Mapster" };
       
       // 使用已配置的全局映射规则
       var destination = source.Adapt<Destination>();

       Console.WriteLine($"Id: {destination.Id}, Name: {destination.Name}");  // Name 会变成大写
  }
}

在这个例子中,我们通过 TypeAdapterConfig<Source, Destination>.NewConfig() 配置了一个全局的映射规则,所有从 SourceDestination 的映射都会自动应用这个规则,确保 Name 字段在映射过程中被转换为大写。这样,当你处理多个对象映射时,不需要每次都重新配置映射规则。

2. 性能优化

Mapster 的设计使其在执行对象映射时具有极高的性能。Mapster 使用了代码生成技术,以避免传统反射带来的性能开销。在默认情况下,Mapster 会使用反射进行映射,但你可以启用代码生成来进一步提高性能。

启用代码生成

为了启用代码生成,你只需要在项目中安装 Mapster.Generator 包:

Install-Package Mapster.Generator

启用代码生成后,Mapster 会在编译时生成源代码,代替运行时反射,极大提升映射速度。

dotnet build

然后你就可以在项目中使用 Mapster 的高性能映射,而不必担心性能瓶颈。

3. 支持集合类型的映射

Mapster 不仅支持单个对象之间的映射,还能自动处理集合类型(如 ListArrayIEnumerable 等)。当你需要将一个集合中的每个元素映射到另一个集合时,Mapster 会自动遍历集合并进行逐一映射。

示例:映射 List 集合
using Mapster;
using System;
using System.Collections.Generic;

public class Source
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Destination
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Program
{
   public static void Main()
  {
       var sourceList = new List<Source>
      {
           new Source { Id = 1, Name = "Alice" },
           new Source { Id = 2, Name = "Bob" }
      };

       // 映射 List<Source> 到 List<Destination>
       var destinationList = sourceList.Adapt<List<Destination>>();

       foreach (var dest in destinationList)
      {
           Console.WriteLine($"Id: {dest.Id}, Name: {dest.Name}");
      }
  }
}

在这个例子中,Mapster 会自动将 List<Source> 映射为 List<Destination>。通过使用 Adapt<List<Destination>>(),Mapster 会逐个映射 Source 列表中的元素。

4. 并行映射

在处理大量数据时,Mapster 还提供了并行映射的支持。通过并行映射,可以加速数据转换过程,特别是在多核处理器上,能够显著提高性能。

示例:并行映射
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;

public class Source
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Destination
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Program
{
   public static void Main()
  {
       var sourceList = new List<Source>
      {
           new Source { Id = 1, Name = "Alice" },
           new Source { Id = 2, Name = "Bob" },
           new Source { Id = 3, Name = "Charlie" }
      };

       // 使用并行映射
       var destinationList = sourceList.AsParallel().Adapt<List<Destination>>();

       foreach (var dest in destinationList)
      {
           Console.WriteLine($"Id: {dest.Id}, Name: {dest.Name}");
      }
  }
}

在这个例子中,我们使用了 AsParallel() 方法将 List<Source> 转换为并行序列。通过这种方式,Mapster 会并行执行映射操作,极大地加速了大数据集的映射过程。需要注意的是,并行映射适合于处理计算密集型的映射任务,但对于简单的映射任务,使用并行可能并不会带来明显的性能提升,反而可能增加额外的线程调度开销。

 

总结

Mapster 是一款高效、灵活且易用的对象映射工具,适用于多种场景。本文介绍了从基础的对象映射到高级特性(如集合映射、嵌套映射、条件映射、自定义转换等)的各种用法,帮助你在实际开发中更加高效地处理对象映射任务。

无论是在多层架构的项目中处理 DTO 和实体类的转换,还是在跨系统的数据交换中进行数据映射,Mapster 都能够提供强大而简洁的解决方案。如果你正在寻找一款高效的对象映射库,Mapster无疑是一个值得尝试的好选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/827201.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

合规监管新趋势!智能合同审查免费体验,提升法律行业合同管理效率

思通数科 思通数据 思通数科推出的智能合同审查系统为这些痛点提供了解决方案。借助大模型、OCR和信息抽取等先进技术,系统具备高效要素抽取、自动分类、合同比对和合同审查等功能。以下是该系统的主要功能及用户体验案例,展示了在法律行业中的实际应用效果。应用案例:法律行…

UE Slate渲染流程

【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!一、前言本文将深入探讨Slate的渲染流程及其相关细节。将详细讲解Slate如何将UI元素渲染到屏幕上,以及它是如何处理各种渲染细节以实现…

【HT-030-Div.1】核桃NOIP组周赛 赛后总结

总结T2爆零了,核桃oj不能缩放 别人题目(100%)我的题目(125%)

PCIe系列专题之二:2.5 Flow Control缓存架构及信用积分

一、故事前传 之前我们讲了对PCIe的一些基础概念作了一个宏观的介绍,了解了PCIe是一种封装分层协议(packet-based layered protocol),主要包括事务层(Transaction layer), 数据链路层(Data link layer)和物理层(Physical layer)。较为详细解释请见之前的文章: 1. PCIe技…

PCIe系列专题之二:2.7 Flow Control的实现过程

一、故事前传 之前我们讲了对PCIe的一些基础概念作了一个宏观的介绍,了解了PCIe是一种封装分层协议(packet-based layered protocol),主要包括事务层(Transaction layer), 数据链路层(Data link layer)和物理层(Physical layer)。较为详细解释请见之前的文章: 1. PCIe技…

cron定时任务报错PAM unable to dlopen(pam_tally2.so): /lib/security/pam_tally2.so

在Ubuntu 22.04中,pam_tally2模块可能已经不再被支持或包含在系统默认的PAM模块中。因此,当系统尝试加载该模块时,无法找到对应的.so文件,需要使用pam_faillock.so来代替 先查找下是否存在pam_faillock.so模块 find /usr -name "pam_*.so"没有 pam_tally2.so ,复…

vue3 如何使用router路由表 创建 Menu 导航菜单

vue3 如何使用router路由表 创建 Menu 导航菜单1. vue3 如何使用router路由表 创建 Menu 导航菜单1.1. 安装 Vue Router1.2. 设置路由1.3. 在主应用中使用路由1.4. 创建导航菜单组件1.5. 在布局中使用导航菜单 1. vue3 如何使用router路由表 创建 Menu 导航菜单 在 Vue 3 中集…

PCIe系列专题之二:2.0 Transaction layer事务层概述

一、故事前传 上回我们对PCIe的一些基础概念作了一个宏观的介绍,了解了PCIe是一种封装分层协议(packet-based layered protocol),主要包括事务层(Transaction layer), 数据链路层(Data link layer)和物理层(Physical layer)。较为详细解释请见之前的文章:PCIe技术概述;…

Linux 中sed命令删除文本中第一个指定符号及其之前的内容

001、[root@PC1 test1]# ls a.txt [root@PC1 test1]# cat a.txt ## 测试数据 fasp.sra.ebi.ac.uk:/vol1/fastq/SRR131/072/SRR13178372/SRR13178372.fastq.gz;fasp.sra.ebi.ac.uk:/vol1/fastq/SRR131/072/SRR13178372/SRR13178372_1.fastq.gz;fasp.sra.ebi.ac.uk:/vol1/fa…

SATA系列专题之六:浅析NCQ原生指令序列

一、故事前传 在之前的文章中, 我们已经针对SATA相关内容进行了较为详细的解析,如果感兴趣的话,请见之前文章:1,浅析SATA Physical Layer物理层OOB信号; 2,SATA Link Layer链路层解析2.0-2.3; 3,SATA Transport Layer传输层解析3.0-3.4; 4,SATA Command Layer命令层解…

SATA系列专题之三:3.3 Transport Layer传输层Flow Control机制解析

一、故事前传 在之前的文章中,已经解析了SATA协议的部分相关内容。较为详细解释请见之前的文章: 1,浅析SATA Physical Layer物理层OOB信号; 2,SATA Link layer链路层解析2.0-2.3; 3,SATA Transport layer链路层解析3.0-3.2;我们这里主要解析Transport layer Flow Contr…

ipv6解析导致 blackbox_exporter 采集http监控项超时问题

排查过程 打开blackbox_exporter后台 http://127.0.0.1:9115/ 找到监控项对应的 Debug Logs点开查看日志: Logs for the probe: ts=2024-11-05T06:38:25.081157873Z caller=main.go:304 module=http_2xx target=http://img.xxx.cn/test.jpg level=info msg="Beginning pr…