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

已配置Ignore,AutoMapper仍清空集合的原因求助

AutoMapper 10.1.1多层映射中集合属性被清空的问题及解决方案

问题场景

使用AutoMapper 10.1.1,因无法升级至.NET Standard 2.1,无法更新到AutoMapper 12.0.1。在多层映射(FromA→ToA,嵌套FromB→ToB)时,已配置Ignore()的ToB.MemberC(ICollection<ToC>类型)被自动设置为空数组,其他Ignore()属性正常保留目标值。

涉及类结构:

// 源端
class FromA {
    // ...其他属性...
    public FromB MemberB { get; set; }
}

class FromB {
    // ...其他属性...
}

// 目标端
class ToA {
    // ...其他属性...
    public ToB MemberB { get; set; }
}

class ToB {
    // ...其他属性...
    public ICollection<ToC> MemberC { get; set; }
}

class ToC {
    // ...其他属性...
}

原映射配置:

// 自定义成员值解析器
internal class TypeMappingMemberValueResolver<TSource, TDestination, TSourceMember, TDestinationMember>
    : IMemberValueResolver<TSource, TDestination, TSourceMember, TDestinationMember>
{
    public TDestinationMember Resolve(TSource source, TDestination destination, TSourceMember sourceMember, TDestinationMember destMember, ResolutionContext context)
    {
        return context.Mapper.Map<TSourceMember, TDestinationMember>(sourceMember, destMember);
    }
}

// 映射配置
CreateMap<FromA, ToA>()
    // ...其他配置...
    .ForMember(to => to.MemberB, opt => opt.MapFrom(new TypeMappingMemberValueResolver<FromA, ToA, FromB, ToB>(src => src.MemberB)))
    // ...其他配置...

CreateMap<FromB, ToB>()
    // ...其他配置...
    .ForMember(to => to.MemberC, opt => opt.Ignore())

执行映射后,instanceOfToA.MemberB.MemberC被清空为空数组,而非保留原有值。

问题分析

在AutoMapper 10.x版本中,多层嵌套映射结合自定义成员解析器时,集合类型的Ignore()规则可能被内部的集合默认处理逻辑覆盖。当通过顶层映射间接触发嵌套映射时,AutoMapper会对目标集合执行初始化或清空操作,忽略已配置的保留规则。

解决方案

1. 移除自定义成员值解析器,使用默认嵌套映射

自定义解析器可能触发了额外的映射逻辑,改用AutoMapper默认的嵌套映射即可避免该问题:

CreateMap<FromA, ToA>()
    // ...其他配置...
    // 无需自定义解析器,AutoMapper会自动使用已注册的FromB→ToB映射
    .ForMember(to => to.MemberB, opt => opt.MapFrom(src => src.MemberB))
    // 甚至可省略该行,因为属性名完全匹配,AutoMapper会自动映射

2. 强化ToB.MemberC的忽略配置

结合Precondition、UseDestinationValue和Ignore,强制AutoMapper不修改目标集合:

CreateMap<FromB, ToB>()
    // ...其他配置...
    .ForMember(to => to.MemberC, opt => 
    {
        opt.Precondition((src, dest) => false); // 永远不执行映射
        opt.UseDestinationValue(); // 强制保留目标值
        opt.Ignore();
    })

3. 在顶层映射中直接忽略深层集合属性

跳过中间层,直接在FromA→ToA的映射中配置忽略MemberB.MemberC:

CreateMap<FromA, ToA>()
    // ...其他配置...
    .ForMember(to => to.MemberB.MemberC, opt => opt.Ignore())

4. 手动处理嵌套对象映射,绕过自动集合逻辑

通过AfterMap手动执行FromB→ToB的映射,避免顶层映射触发的额外集合处理:

CreateMap<FromA, ToA>()
    // ...其他配置...
    .ForMember(to => to.MemberB, opt => opt.Ignore()) // 先忽略自动映射
    .AfterMap((src, dest) => 
    {
        if (src.MemberB != null && dest.MemberB != null)
        {
            // 手动映射到已存在的目标对象
            Mapper.Map(src.MemberB, dest.MemberB);
        }
    })

最终建议

优先尝试方案1或方案4,这两个方案能直接规避AutoMapper旧版本的集合处理bug。若所有配置方案均无效,则只能考虑升级至.NET Standard 2.1并使用AutoMapper 12.0.1,该版本已修复多个嵌套映射和集合处理的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:39:55