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

protobuf-net3.x使用编译TypeModel时嵌套Dictionary序列化报错咨询

问题原因

protobuf-net 3.x 版本并未废弃该使用流程,错误是由于 3.x 对预编译模型的类型注册逻辑做了调整导致的:

  • 2.x 版本的 RuntimeTypeModel 在调用 Compile() 时,会自动递归扫描所有已注册类型的成员涉及的所有类型,自动为泛型集合等内置类型生成序列化器
  • 3.x 版本默认只会为主动调用 Add() 方法注册到 RuntimeTypeModel 的类型生成序列化器,嵌套的 Dictionary<int, int> 没有被显式注册,因此编译后的模型找不到对应的序列化器,抛出异常。
解决方法
  • 方法1:显式注册所有嵌套用到的泛型集合类型
    只需要在注册TestClass的代码后,补充注册内部用到的Dictionary<int, int>即可,不需要额外配置,修改后可运行代码如下:
void Main()
{
    RuntimeTypeModel newTypeModel = RuntimeTypeModel.Create();
    newTypeModel.Add(typeof(TestClass), applyDefaultBehaviour: true);
    // 新增这一行,显式注册嵌套的集合类型
    newTypeModel.Add(typeof(Dictionary<int, int>), applyDefaultBehaviour: true);
    var compiledModel = newTypeModel.Compile();

    var testObj = new TestClass();
    testObj.Data = new Dictionary<int, Dictionary<int, int>>();

    using (var ms = new MemoryStream())
    {
        compiledModel.Serialize(ms, testObj);
        byte[] data = ms.ToArray();
        data.Dump();
    }
}

[ProtoContract]
public class TestClass : Extensible
{
    [ProtoMember(1)]
    public Dictionary<int, Dictionary<int, int>> Data { get; set; }
}
  • 方法2:直接使用RuntimeTypeModel实例序列化
    如果对序列化性能没有极致要求,可以不用调用Compile()生成预编译模型,直接用RuntimeTypeModel实例执行序列化,运行时模型会自动探测所有需要的序列化器,不需要手动注册嵌套类型。
  • 方法3:使用源生成器替代运行时编译模型
    3.x版本新增了源生成器功能,可以在编译期自动生成所有需要的序列化代码,不需要手动管理类型注册,稳定性和性能都优于运行时编译的模型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 07:39:03