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

如何通过属性保留引用?AutoMapper处理Revit循环引用异常求助

Understanding AutoMapper's PreserveReferences() and Fixing Your Circular Reference Stack Overflow

Let's break down why you're still hitting a StackOverflowException even after using PreserveReferences(), and how to fix it by customizing equality checks for your mappings.

How PreserveReferences() Works by Default

AutoMapper's PreserveReferences() relies on reference equality (checking if two objects are the exact same instance in memory) to detect and break circular references during mapping. This works smoothly for most scenarios where source and destination objects align by reference.

But here's the key issue in your case: when mapping from Revit API's Element/Parameter to your custom Models.Element/Models.Parameter, AutoMapper is creating entirely new instances of your destination models. The default reference equality check can't track that a mapped Models.Parameter refers to the same Models.Element it already processed—since those are new objects, not the same reference. This leads to infinite recursive mapping and the stack overflow.

Customizing Equality Checks for Preserved References

Good news: AutoMapper lets you override the equality logic for preserved references with the .EqualityComparison() method. Since your Models.Element already uses Id for equality checks (via overridden Equals() and GetHashCode()), we can hook that logic into AutoMapper's reference tracking.

Updated Mapping Configuration

Modify your profile to add custom equality comparisons to both mappings, using the Id property to identify duplicate entities:

profile.CreateMap<Element, Models.Element>()
    .ForMember(element => element.Id, expression => expression.MapFrom(element => element.Id.IntegerValue))
    .IncludeAllDerived()
    .PreserveReferences()
    .EqualityComparison((srcRevitElement, destCustomElement) => 
        srcRevitElement.Id.IntegerValue == destCustomElement.Id);

profile.CreateMap<Parameter, Models.Parameter>()
    .ForMember(parameter => parameter.Id, expression => expression.MapFrom(parameter => parameter.Id.IntegerValue))
    .IncludeAllDerived()
    .PreserveReferences()
    .EqualityComparison((srcRevitParam, destCustomParam) => 
        srcRevitParam.Id.IntegerValue == destCustomParam.Id);

Why This Fixes the Stack Overflow

  • AutoMapper now tracks mapped destination objects using their Id instead of memory reference.
  • When it encounters a Parameter that references an Element it's already mapped, it reuses the existing Models.Element instance instead of creating a new one. This breaks the circular mapping chain that caused the infinite recursion.

Quick Additional Tip

For consistency, consider adding Equals() and GetHashCode() overrides to your Models.Parameter class as well, mirroring what you did for Models.Element. This ensures equality checks work reliably across all your mapped models.

内容的提问来源于stack exchange,提问作者Romain DA ROCHA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:19:44