在现代开发中,对象之间的转换是常见且繁琐的任务,尤其是在多层架构或跨系统数据传输的场景下。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
被拆分为 FirstName
和 LastName
。通过自定义转换函数,你可以在映射过程中进行更多的数据处理。
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()
配置了一个全局的映射规则,所有从 Source
到 Destination
的映射都会自动应用这个规则,确保 Name
字段在映射过程中被转换为大写。这样,当你处理多个对象映射时,不需要每次都重新配置映射规则。
2. 性能优化
Mapster 的设计使其在执行对象映射时具有极高的性能。Mapster 使用了代码生成技术,以避免传统反射带来的性能开销。在默认情况下,Mapster 会使用反射进行映射,但你可以启用代码生成来进一步提高性能。
启用代码生成
为了启用代码生成,你只需要在项目中安装 Mapster.Generator
包:
Install-Package Mapster.Generator
启用代码生成后,Mapster 会在编译时生成源代码,代替运行时反射,极大提升映射速度。
dotnet build
然后你就可以在项目中使用 Mapster 的高性能映射,而不必担心性能瓶颈。
3. 支持集合类型的映射
Mapster 不仅支持单个对象之间的映射,还能自动处理集合类型(如 List
、Array
、IEnumerable
等)。当你需要将一个集合中的每个元素映射到另一个集合时,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 是一款高效、灵活且易用的对象映射工具,适用于多种场景。本文介绍了从基础的对象映射到高级特性(如集合映射、嵌套映射、条件映射、自定义转换等)的各种用法,帮助你在实际开发中更加高效地处理对象映射任务。