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

如何用AutoMapper将Colli列表映射为数量扩容的ColliDto列表?

问题:AutoMapper实现按Count生成对应数量的Dto列表

现有类定义

public class Colli
{
    public int Count { get; set; }
    public string Description { get; set; }
}

public class Shipment
{
    public List<Colli> Collis { get; set; }
}

public class ShipmentDto
{
    public List<ColliDto> Collis { get; set; }
}

public class ColliDto
{
    public string Description { get; set; }
}

需求说明

根据每个Colli的Count值,生成对应数量、描述相同的ColliDto列表。

示例输入:

{
    "collis": [
        {
            "count": 2,
            "description": "Colli 1"
        },
        {
            "count": 1,
            "description": "Colli 2"
        }
    ]
}

示例输出:

{
    "collis": [
        {
            "description": "Colli 1"
        },
        {
            "description": "Colli 1"
        },
        {
            "description": "Colli 2"
        }
    ]
}

尝试的实现及问题

编写了如下ITypeConverter转换器,期望将单个Colli转为对应数量的List<ColliDto>:

public class ColliConverter : ITypeConverter<Colli, List<ColliDto>>
{
    public List<ColliDto> Convert(Colli source, List<ColliDto> destination, ResolutionContext context)
    {
        var retval = new List<ColliDto>();
        for (int i = 0; i < source.Count; i++)
        {
            retval.Add(context.Mapper.Map<ColliDto>(source));
        }
        return retval;
    }
}

并配置映射:

CreateMap<Colli, List<ColliDto>>().ConvertUsing<ColliConverter>();

但调试发现转换器未被调用。

解决方案

这个需求完全可以通过AutoMapper实现,无需手动全量映射。之前的转换器未生效的原因是:AutoMapper处理List<Colli>到List<ColliDto>时,默认会逐个将Colli映射为ColliDto,而非调用单个Colli到List<ColliDto>的转换器。正确的做法是针对Shipment到ShipmentDto的Collis字段配置转换逻辑。

方式一:自定义值解析器(ValueResolver)

定义一个值解析器来处理Collis字段的展开逻辑:

public class CollisResolver : IValueResolver<Shipment, ShipmentDto, List<ColliDto>>
{
    private readonly IMapper _mapper;

    public CollisResolver(IMapper mapper)
    {
        _mapper = mapper;
    }

    public List<ColliDto> Resolve(Shipment source, ShipmentDto destination, List<ColliDto> destMember, ResolutionContext context)
    {
        var result = new List<ColliDto>();
        foreach (var colli in source.Collis)
        {
            for (int i = 0; i < colli.Count; i++)
            {
                result.Add(_mapper.Map<ColliDto>(colli));
            }
        }
        return result;
    }
}

然后配置映射关系:

// 先配置Colli到ColliDto的基础字段映射(如果有更多字段,AutoMapper会自动匹配同名字段)
CreateMap<Colli, ColliDto>();

// 配置Shipment到ShipmentDto的映射,指定Collis字段使用自定义解析器
CreateMap<Shipment, ShipmentDto>()
    .ForMember(dest => dest.Collis, opt => opt.MapFrom<CollisResolver>());

方式二:直接在映射配置中使用自定义逻辑

如果不需要单独的解析器类,也可以直接在映射配置中写逻辑:

CreateMap<Colli, ColliDto>();

CreateMap<Shipment, ShipmentDto>()
    .ForMember(dest => dest.Collis, opt => opt.MapFrom(src => 
        src.Collis.SelectMany(colli => 
            Enumerable.Repeat(_mapper.Map<ColliDto>(colli), colli.Count)
        ).ToList()
    ));

以上两种方式都能实现需求,无需手动编写全量映射代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 18:25:39