【发布时间】:2011-11-11 11:54:39
【问题描述】:
如this post 中所述,我们可以使用ProtoInclude 属性来管理类层次结构序列化。如果我们只使用 protobuf-net,它在两个方向上都可以正常工作。但是当我们尝试反序列化由“外部”遗留协议缓冲区实现序列化的消息时会出现问题,例如。 Java等
正如上面那篇文章中提到的,当子类字段在父类之前序列化时,Protobuf-net 通过“反转”字节序列识别类层次结构。但是遗留代码以“正确”的顺序将它们序列化,并且 protobuf-net 在反序列化过程中抛出 “无法将 'A' 类型的对象转换为 'B' 类型。” 异常。相反,它工作正常,遗留代码可以反序列化 protobuf-net 库产生的“分层”消息。
我不能影响管道另一侧的字节序列化顺序。如何在 .NET protobuf-net 端正确反序列化此类消息?
更新:代码示例
在我们的最后,我们有原始的 protobuf-net 分层类:
[ProtoContract, ProtoInclude(10, typeof(B))]
public class A
{
[ProtoMember(1)]
public int Age;
}
public class B : A
{
[ProtoMember(2)]
public int Balls;
}
另一方面,类是使用 .proto 文件生成的:
message B {
optional int32 balls = 2;
}
message A {
optional int32 age = 1;
optional B b = 10;
}
生成类示例,我们可以使用 protobuf-net 生成器为 .NET 创建它们:
[ProtoContract]
public class A_generated
{
[ProtoMember(1)]
public int Age;
[ProtoMember(10)]
public B b;
}
[ProtoContract]
public class B_generated
{
[ProtoMember(2)]
public int Balls;
}
那么现在,让我们序列化和反序列化 B 类:
- 序列化和反序列化回原始类 - 好的
- 序列化和反序列化返回生成的类 - 好的
- 序列化原始并反序列化为生成 - 好的
- 序列化生成并反序列化为原始 - FAIL,“无法将'A'类型的对象转换为'B'类型'." 异常
我调查了结果字节并发现了一个差异 - 字节顺序。
示例:让 Age=10 和 Balls=23。那么:
- original B 序列化:[82, 2, 16, 23, 8, 10],可以将两者作为 original 作为 generated 类进行反序列化;
- 生成 B 序列化:[8, 10, 82, 2, 16, 23],不能使用上面的 protobuf-net original 类进行反序列化。
我希望现在已经足够清楚,并希望得到肯定的答案:是的,有一种方法可以使用 ProtoInclude 和反序列化泛型类。
【问题讨论】:
-
你能更具体地介绍一下这里的场景吗?我的印象是常规的 protobuf 不包括继承。因此,它经常通过封装进行填充。此外,您可以只使用现有的 .proto 来生成模型...?很乐意提供帮助,但我想确保我的回答正确。
-
啊,对。我现在明白上下文了,谢谢。我明白发生了什么,以及为什么。我将在今天晚些时候进行调查,看看是否有简单的解决方法。
-
非常小,但是 A_generated.b 应该输入为 B_generated 吗?这并不能解决问题 - 我只是想在我的测试中保持精确......
-
我花了几个小时研究这个。我同意支持是可取的(编码规范相当清楚,实现应该以任何顺序处理字段),但是实现......并不明显。完成这项工作需要相当多的努力。
-
谢谢,期待您的答复,希望能修复。 :)
标签: .net inheritance protocol-buffers protobuf-net