You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用AutoMapper实现嵌套对象的映射?

问题描述

现有如下实体类与DTO类:

实体与基础DTO

public class MyEntity
{
    public string Name {get; set;}
}

public class MyEntityDto
{
    public string Name {get;set;}
}

聚合类与对应DTO

public class MyAgg
{
    public string SomeProp {get;set;}
    public MyEntity Entity {get;set;}
}

public class MyAggDto
{
    public string SomeProp {get;set;}
    public AggDataDto Data {get;set;}
    
    public class AggDataDto
    {
        public MyEntityDto Entity {get;set;}
    }
}

映射配置类

public class MyProfile : Profile
{
    public MyProfile()
    {
        CreateMap<MyEntity, MyEntityDto>();
        CreateMap<MyAgg, MyAggDto>()
            .ForMember(dest => dest.Data, opt => opt.MapFrom(src => {
                return new MyAggDto.AggDataDto
                {
                    /*
                        我能否在此处注入并使用IMapper,从src.Entity获取MyEntityDto?
                        我应该用new MyEntityDto(...)创建Dto吗?
                        还有其他方法吗?
                    */
                    Entity = ...
                }
            }));
    }
}

需要实现MyAgg到MyAggDto的嵌套对象映射,具体是将MyAgg.Entity转换为MyAggDto.Data.Entity(即MyEntityDto)。

解决方案

方法一:利用AutoMapper自动映射嵌套结构

最简洁的方式是给嵌套的AggDataDto添加映射规则,让AutoMapper自动复用已有的MyEntity→MyEntityDto映射:

public class MyProfile : Profile
{
    public MyProfile()
    {
        // 基础映射
        CreateMap<MyEntity, MyEntityDto>();
        
        // 配置MyAgg到AggDataDto的映射,将MyAgg.Entity映射到AggDataDto.Entity
        CreateMap<MyAgg, MyAggDto.AggDataDto>()
            .ForMember(dest => dest.Entity, opt => opt.MapFrom(src => src.Entity));
        
        // 配置MyAgg到MyAggDto的映射,直接将源对象映射到Data属性
        CreateMap<MyAgg, MyAggDto>()
            .ForMember(dest => dest.Data, opt => opt.MapFrom(src => src));
    }
}

AutoMapper会自动递归处理嵌套映射,无需手动构造对象,维护性最好。

方法二:通过映射上下文获取IMapper实例

如果需要手动构造AggDataDto,可以在ResolveUsing中通过映射上下文(ResolutionContext)获取IMapper实例,复用已有的映射规则:

public class MyProfile : Profile
{
    public MyProfile()
    {
        CreateMap<MyEntity, MyEntityDto>();
        
        CreateMap<MyAgg, MyAggDto>()
            .ForMember(dest => dest.Data, opt => opt.ResolveUsing((src, dest, _, context) => 
            {
                return new MyAggDto.AggDataDto
                {
                    // 利用上下文的Mapper实例执行已有映射
                    Entity = context.Mapper.Map<MyEntityDto>(src.Entity)
                };
            }));
    }
}

这种方式适合需要在构造嵌套对象时添加额外逻辑的场景,比如判断src.Entity是否为null等。

方法三:手动构造DTO(不推荐)

可以手动new MyEntityDto并赋值,但这种方式硬编码属性,一旦MyEntity或MyEntityDto的属性变更,需要同步修改这里的代码,违反DRY原则,仅适合简单场景:

public class MyProfile : Profile
{
    public MyProfile()
    {
        CreateMap<MyEntity, MyEntityDto>();
        
        CreateMap<MyAgg, MyAggDto>()
            .ForMember(dest => dest.Data, opt => opt.MapFrom(src => 
            {
                return new MyAggDto.AggDataDto
                {
                    Entity = src.Entity != null ? new MyEntityDto { Name = src.Entity.Name } : null
                };
            }));
    }
}

内容的提问来源于stack exchange,提问作者acmoune

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 18:15:05