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

MongoDB C#驱动2.3版本嵌套字典反序列化问题求助

MongoDB C#驱动2.3版本嵌套字典接口反序列化修复方案

问题根源

升级到2.3驱动后,旧的全局自定义IDiscriminatorConvention会递归处理字典里的IHtmlCompositeBlockItem接口,导致栈溢出。必须针对字典的接口值类型单独配置鉴别逻辑,避免全局递归。

分步解决

1. 编写专属接口鉴别器

只处理IHtmlCompositeBlockItem的类型映射,不要全局套用:

public class HtmlCompositeBlockItemDiscriminator : IDiscriminatorConvention
{
    public string DiscriminatorKey => "_t";

    public Type GetActualType(IBsonReader reader, Type nominalType)
    {
        // 定位并读取存储的鉴别器字段
        var bookmark = reader.GetBookmark();
        reader.FindElement(DiscriminatorKey);
        var typeName = reader.ReadString();
        reader.ReturnToBookmark(bookmark);

        // 按项目中实际实现类型映射,自行补充所有子类
        return typeName switch
        {
            "HtmlTextBlockItem" => typeof(HtmlTextBlockItem),
            "HtmlImageBlockItem" => typeof(HtmlImageBlockItem),
            _ => nominalType
        };
    }

    public BsonValue GetDiscriminator(Type nominalType, Type actualType)
    {
        // 存储类型名称作为鉴别器,和旧数据格式保持一致
        return actualType.Name;
    }
}

2. 为字典属性单独配置序列化器

在IHtmlCompositeBlock实现类的映射配置中,给LocalizedItems绑定专用序列化器:

BsonClassMap.RegisterClassMap<YourCompositeBlockImpl>(cm =>
{
    cm.AutoMap();
    // 针对字典的值类型(IHtmlCompositeBlockItem)配置鉴别器
    cm.MapMember(block => block.LocalizedItems)
      .SetSerializer(new DictionarySerializer<int, IHtmlCompositeBlockItem>(
          new Int32Serializer(),
          new InterfaceImplementerSerializer<IHtmlCompositeBlockItem>(new HtmlCompositeBlockItemDiscriminator())
      ));
});

3. 关键注意事项

  • 禁止全局注册鉴别器,否则会触发递归处理字典内的接口对象,直接导致栈溢出
  • 确保数据库旧数据中的_t字段值,和鉴别器里的类型名称完全匹配
  • InterfaceImplementerSerializer是2.x驱动自带的接口反序列化专用类,比全局鉴别器更精准

验证方法

读取旧数据时,检查是否能正确实例化IHtmlCompositeBlockItem的各个具体子类;写入新数据时,确认_t字段被正确添加到每个字典值对象中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:53:17