1. 手动映射
LINQ
C#
IQueryable<Entity>.Select(item=> new DTO{});
IQuertable<Entity>.ForEachAsync(item=> new DTO{})
循环
C#
foreach(var item in IQueryable<Entity>)
{
DTO model = new(){}
List<Entity>.Add(model);
}
2. 序列化
System.Text.Json
C#
JsonSerializer.Deserialize<T>(Entity,options);
Newtonsoft.Json
C#
JsonConvert.DeserializeObject<T>(Entity,options);
3. 对象映射框架
AutoMapper
AutoMapper的配置
C#
public class AutoMapperConfigs:Profile
{
//通过构造函数把DTO映射到数据库实体,映射方向:左边映射到右边
public AutoMapperConfigs()
{
//角色
CreateMap<RoleAdd, Role>();
CreateMap<RoleEdit, Role>();
//用户
CreateMap<UserAdd,Users>();
CreateMap<UserEdit, Users>();
//菜单
CreateMap<MenuAdd, Menu>();
CreateMap<MenuEdit, Menu>();
}
}
//AutoMapper映射
builder.Services.AddAutoMapper(typeof(AutoMapperConfigs));
AutoMapper使用
C#
public class EntityService(IMapper _mapper)
{
DTO model = _mapper.Map<Entity>(Entity)
}
Mapster
C#
EntityDTO model = Entity.Adapt<EntityDTO>();
4. 表达式树
C#
public static Func<Source, Dest> CreateMapper()
{
var sourceParam = Expression.Parameter(typeof(Source), "src");
var bindings = new List<MemberBinding>();
foreach (var srcProp in typeof(Source).GetProperties())
{
var destProp = typeof(Dest).GetProperty(srcProp.Name);
if (destProp != null)
{
bindings.Add(Expression.Bind(destProp,
Expression.Property(sourceParam, srcProp)));
}
}
return Expression.Lambda<Func<Source, Dest>>(
Expression.MemberInit(Expression.New(typeof(Dest)), bindings),
sourceParam).Compile();
}
5. Source Generators
零运行时开销
生成映射代码
C#
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;
[Generator]
public class MapperGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
// 注册语法接收器
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context)
{
// 获取语法接收器中的类信息
if (context.SyntaxReceiver is not SyntaxReceiver receiver)
return;
// 生成映射代码
foreach (var classSymbol in receiver.ClassesToMap)
{
string source = GenerateMappingCode(classSymbol);
context.AddSource($"{classSymbol.Name}_Mapper.cs", SourceText.From(source, Encoding.UTF8));
}
}
private string GenerateMappingCode(INamedTypeSymbol classSymbol)
{
string className = classSymbol.Name;
string dtoClassName = $"{className}Dto";
StringBuilder code = new StringBuilder();
code.AppendLine("using System;");
code.AppendLine();
code.AppendLine($"namespace {classSymbol.ContainingNamespace.ToDisplayString()}");
code.AppendLine("{");
code.AppendLine($" public static partial class {className}Mapper");
code.AppendLine(" {");
code.AppendLine($" public static {dtoClassName} MapToDto({className} source)");
code.AppendLine(" {");
code.AppendLine($" return new {dtoClassName}");
code.AppendLine(" {");
// 生成属性映射代码
foreach (var property in classSymbol.GetMembers().OfType<IPropertySymbol>())
{
string propertyName = property.Name;
code.AppendLine($" {propertyName} = source.{propertyName},");
}
code.AppendLine(" };");
code.AppendLine(" }");
code.AppendLine(" }");
code.AppendLine("}");
return code.ToString();
}
}