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
相关产品推荐
相关产品推荐

