对象映射与转换的解决方案

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();
    }
}
订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
滚动至顶部