Protobuf-net Inheritance: ProtoInclude and Compatibility

As described in this post , we can use the ProtoInclude attribute to control the serialization of the class hierarchy. And if we use only protobuf-net, it works great in both directions. But the problem arises when we try to deserialize messages serialized by "external" obsolete protocol buffer implementations, for example. Java etc.

As mentioned above, Protobuf-net recognizes the class hierarchy by using "reversed" byte sequences when the fields of the child classes are serialized to the parent. But the inherited code serializes them in the “correct” order, and protobuf-net returns “Unable to pass an object of type“ A ”to type“ B. Exception during deserialization. It works fine in the opposite direction, outdated code can deserialize “hierarchical” messages, created by protobuf-net library.

I cannot affect the sort order of bytes on the opposite side of the pipe. How to properly deserialize this type of message on the .NET side of protobuf-net?

Update: Code Samples

At our end of the line, we have the original protobuf-net hierarchical classes:

[ProtoContract, ProtoInclude(10, typeof(B))] public class A { [ProtoMember(1)] public int Age; } public class B : A { [ProtoMember(2)] public int Balls; } 

At the other end of the line, classes are created using the .proto file:

 message B { optional int32 balls = 2; } message A { optional int32 age = 1; optional B b = 10; } 

Given class examples, we could use the protobuf-net generator to create them for .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; } 

So, let's serialize and deserialize class B:

  • Serialize and deserialize source classes - OK
  • Serialize and deserialize back-created classes - OK
  • Serialize original and deserialize as generated - OK
  • Serialize generated and deserialize as original - FAIL , "Cannot overlay an object of type A on type B." an exception

I examined the resulting bytes and discovered the difference - the byte order .

Example: let Age = 10 and Balls = 23. Then:

  • original B serialized: [82, 2, 16, 23, 8, 10], can be deserialized using both the original and generated classes;
  • serialized B generated: [8, 10, 82, 2, 16, 23], can NOT be deserialized using the original protobuf-net classes above.

Hopefully now it is clear enough and want a positive answer: yes, there is a way to use ProtoInclude and deserialize common classes.

+4
source share
1 answer

Edit: this should be supported in v2 from r616 onwards.


To quote protobuf / java-tutorial :

Do not look for objects similar to class inheritance, although protocol buffers do not.

So: whatever you use locally to impose inheritance locally, I would advise: use this here too. For example, you can run your .proto through a protogen.

If you can be very specific about the layout on both sides (e.g. .proto example), I could still consult.

+1
source

Source: https://habr.com/ru/post/1380752/


All Articles