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

使用IValueResolver时AutoMapper为何抛出StackOverflowException异常?

问题分析与解决方案

你的代码确实错误使用了IValueResolver,核心问题是在Resolver中调用context.Mapper.Map时没有传递当前的ResolutionContext,导致AutoMapper无法跟踪已创建的实例,没法正确处理循环引用。

修复要点

  • 在Resolver的Resolve方法中,调用Map时必须传入当前的ResolutionContext,让AutoMapper在同一个映射会话中管理实例。
  • 在映射配置中启用循环引用处理,使用PreserveReferences()来告诉AutoMapper保留对象引用,避免循环引用引发的无限递归或重复创建对象。

修正后的完整代码

using AutoMapper;

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        B b = new B();

        a.B = b;
        b.List.Add(a);

        var mapper = new Mapper(new MapperConfiguration(cfg => { cfg.AddProfile<Profile1>(); }));

        var model = mapper.Map<AModel>(a);
    }
}

class A
{
    public B B { get; set; }
}

class B
{
    public List<A> List { get; set; }

    public B()
    {
        List = new List<A>();
    }
}

class AModel
{
    public BModel B { get; set; }
}

class BModel
{
    public List<AModel> List { get; set; }
}

class Profile1 : Profile
{
    public Profile1()
    {
        CreateMap<A, AModel>()
            .PreserveReferences() // 启用循环引用处理
            .ForMember(x => x.B, o => o.MapFrom<ValueResolver1>());
        CreateMap<B, BModel>()
            .PreserveReferences(); // 启用循环引用处理
    }
}

class ValueResolver1 : IValueResolver<A, AModel, BModel>
{
    public BModel Resolve(A source, AModel destination, BModel destMember, ResolutionContext context)
    {
        // 传递当前上下文,让AutoMapper跟踪实例
        return context.Mapper.Map<BModel>(source.B, context);
    }
}

原理说明

当你传递context给Map方法时,AutoMapper会在这个上下文的实例缓存中查找是否已经映射过source.B对应的目标对象。如果已经存在,就直接返回已有的实例,而不是创建新的,这样就能正确处理a -> b -> list包含a的循环引用,避免无限递归和重复创建对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 20:43:11