Protobuf-net 中的继承:ProtoInclude 和兼容性

Posted

技术标签:

【中文标题】Protobuf-net 中的继承:ProtoInclude 和兼容性【英文标题】:Inheritance in Protobuf-net: ProtoInclude and compatibility 【发布时间】: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 吗?这并不能解决问题 - 我只是想在我的测试中保持精确...... 我花了几个小时研究这个。我同意支持是可取的(编码规范相当清楚,实现应该以任何顺序处理字段),但是实现......并不明显。完成这项工作需要相当多的努力。 谢谢,期待您的答复,希望能修复。 :) 【参考方案1】:

编辑:从 r616 开始,v2 应该支持这一点。


引用protobuf / java tutorial:

不过,不要去寻找类似于类继承的工具 - 协议缓冲区不会这样做。

所以:无论您在本地使用什么来欺骗本地继承,我都会建议:在这里也使用它。例如,您可以通过 protogen 运行现有的 .proto。

如果您可以非常具体地了解两侧的布局(例如 .proto 示例),我可能会提供进一步的建议。

【讨论】:

@Alex 感谢修复;我一定是在用手机什么的

以上是关于Protobuf-net 中的继承:ProtoInclude 和兼容性的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf-net 中的继承:ProtoInclude 和兼容性

使用protobuf-net继承时如何选择字段号?

关于继承的 ProtoBuf-Net 的问题?

Protobuf-net.Grpc 服务契约继承

用于继承的 Protobuf-net .proto 文件生成

如何停止使用 Protobuf-Net 继承,直接使用继承类?