Protobuf – Handling sub-classes

In this blog post, we will look into how to handle subclasses or interface implementations during protobuf serialization. Consider the following class.

[ProtoContract]
public class Person
{
    [ProtoMember(1)]
    public string FirstName { get; set; }
    [ProtoMember(2)]
    public string LastName { get; set; }
}

For serializing an instance of the above with protobuf-net, you could do it easily as the following.

public static byte[] SerializeObject<T>(T record)
{
    using var stream = new MemoryStream();
    Serializer.Serialize(stream, record);
    return stream.ToArray();
}

However, let us now add some more properties to the class, which would make use of an abstraction or a sub-class. For example,

public interface ISubject
{
    string Name { get; set; }
}

public class Subject : ISubject
{
    
    public string Name { get; set; }
}

[ProtoContract]
public class Person
{
    [ProtoMember(1)]
    public string FirstName { get; set; }
    [ProtoMember(2)]
    public string LastName { get; set; }

    [ProtoMember(3)]
    public IEnumerable<ISubject> Subjects { get; set; }
}

The above code ould fail to serialize as there is a lack of sufficient information regarding the types involved in Subjects. The fix is easy. You could make use of the ProtoInclude for mentioning the possible subtypes.

[ProtoContract]
[ProtoInclude(100,typeof(Subject))]
public interface ISubject
{
    [ProtoMember(1)]
    string Name { get; set; }
}

public class Subject : ISubject
{
    
    public string Name { get; set; }
}

The ProtoInclude attribute is a bit like the XmlInclude attribute for the XmlSerializer – it allows you to explicitly declare the subtypes for each type, which would be used during the (de)serialization.

That’s all for now. As a side note, I wanted to talk about the AsReference property of the ProtoMember attribute, but as of v3.xx, the property has been marked as Obsolete. So until there is an alternative for the same, we will delay the discussion on the same.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s