Protobuf 无法序列化 system.object

Posted

技术标签:

【中文标题】Protobuf 无法序列化 system.object【英文标题】:Protobuf cannot serialize system.object 【发布时间】:2021-01-19 20:43:36 【问题描述】:

我的类具有序列化所需的所有属性,我将它们存储在 system.object 中,这样当另一端反序列化它们时,它可以对它们进行模式匹配并根据对象类型执行不同的操作。

object data = MyObject;
Serializer.SerializeWithLengthPrefix(stream, data, PrefixStyle.Fixed32); // exception happens here

用 XML/BinaryFormatter 等其他序列化方法尝试过,似乎没有问题。

【问题讨论】:

尝试将其转换为您的类型。 Protobuf 需要一个可以序列化的类型,而 System.Object 不能 不,我需要在反序列化时对其进行模式匹配。你可以用 BinaryFormatter 来做,所以我不确定是否要为所有要继承的对象创建一个基类 System.Object 没有序列化所需的属性,因此您的错误。 我是否需要为所有要继承的类创建一个虚拟基类..?似乎是一个可行的想法,但丑陋。 我认为这可能是最好的方法。只要该类可被 protobuf 序列化,您就可以将对象作为该类型传递。 【参考方案1】:

这里的异常非常具有描述性 - protobuf-net 无法序列化 system.object,因为它没有被告知如何序列化/反序列化它。这不是 protobuf-net 的限制,protobuf(规范)是一种合约序列化方法,因此它需要类型的规范才能对其进行序列化。

一种选择是创建一个用 ProtoContract 属性标记的基类并从那里继承。务必使用 ProtoInclude-attribute 将所有子类包含在基类中,否则序列化器将不知道如何序列化子类。

我建议不要这样做,因为子类的序列化是在标准 protobuf 行为之上提供的 protobuf-net 的一种添加,如果您需要使用其他库和/或语言,则会产生问题。相反,我建议您创建一种消息格式,您可以在其中单独编码对象的类型(protobuf 术语中的消息)。例如,将类型编码为枚举,作为消息开头的前 4 个字节,然后是对象本身。然后您可以先读取类型,然后进行相应的反序列化,而无需求助于子类。

【讨论】:

你的意思是这样的:将一个枚举写入例如 Person 调用的流,然后写入 Person 类型的对象?反序列化枚举,检查类型,然后根据枚举结果反序列化类型? @Jackou 是的,就是这样。这还有一个额外的好处,就是您可以跳过对您不感兴趣的消息类型的反序列化,以获得潜在的性能提升。

以上是关于Protobuf 无法序列化 system.object的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf-net 序列化错误 =“一旦生成了序列化程序,就无法更改类型”

无法在 AWS 中使用大象鸟和 Hive 反序列化 Protobuf (2.6.1) 数据

Protobuf-Net 无法在没有无参数构造函数的情况下反序列化记录

无法让 Protobuf-net 与 vb.net 一起使用

使用 protobuf-net 序列化具有接口类型成员的类

protobuf 标签DataFormat =DataFormat.FixedSize解决连续int字段无法解析