Search code examples
c#code-generationprotocol-buffersprotobuf-netsubtype

protobuf-net : how to represent inheritance in messages and generate derived classes?


protobuf-net proto2 c#

Here is my .cs file that works for protobuf-net serialize/deserialize :

[ProtoBuf.ProtoContract(Name=@"MyBaseTypeProto")]
[ProtoBuf.ProtoInclude(typeof(MyDerivedType), 1)]
public partial class MyBaseType { ... }

[ProtoBuf.ProtoContract(Name=@"MyDerivedTypeProto")] 
public partial class MyDerivedType : MyBaseType { ... }

[ProtoBuf.ProtoContract(Name=@"MyMessageProto")]                                                                  
public partial class MyMessage                                          
{                                                                                               
    [ProtoBuf.ProtoMember(1, IsRequired = false, Name = @"MyList", DataFormat = ProtoBuf.DataFormat.Default)]                                                 
    public List<MyDerivedType> MyList;  

Is it possible to compose .proto files so that protogen.exe will generate the above ?

Something like :

MyBaseType.proto
message MyBaseType {
    ...
}

MyDerivedType.proto
message MyDerivedType {
    ...
}

MyMessage.proto
import "MyDerivedType.proto"
message MyMessage{                                                                          
    repeated MyDerivedType MyList = 1;                                                          
}    

but protogen.exe applied to the above message-types will not generate the above classes as desired; specifically it will not generate these lines of code :

[ProtoBuf.ProtoInclude(typeof(MyDerivedType), 1)]

public partial class MyDerivedType : MyBaseType

Solution

  • Protocol buffers doesn't support inheritance in a form that's analogous to (or maps to) intuitive inheritance in C++/C#/Java.

    See here:

    Messages can also be extended, but the method by which this is accomplished differs from familiar C++ or Java-style inheritance. Instead, message extension is implemented by reserving some number of field indices in the base message for use by the extending messages.

    And the protocol buffer docs say:

    Extensions let you declare that a range of field numbers in a message are available for third-party extensions. Other people can then declare new fields for your message type with those numeric tags in their own .proto files without having to edit the original file.

    The first article also discusses several other techniques for approximating polymorphism, with the pros and cons of each.