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.