How to Serialize Inherited Class with ProtoBuf-Net

ScruffyDuck picture ScruffyDuck · Oct 20, 2012 · Viewed 15.3k times · Source

I am sorry if this is a duplicate. I have searched several places for an answer that I might understand including:

ProtoBuf.net Base class properties is not included when serializing derived class

Serialize inherited classes using protobuf-net

My apologies but I did not really understand the answers. I am looking for a faster more compact binary serializer and ProtoBuf looks like it might be the answer. I need to serialize a set of classes that all derive from a single base class. There are a large number of them so before committing to edit the class code I ran a simple test. Also I do not want to modify the classes in any way that might impact deserializing older persisted files generated with the NET binary serializer.

This is the base class:

[ProtoContract]
    public class BaseClass
    {
        [ProtoMember(1)]
        public string Name
        {
            get; set;
        }
        [ProtoMember(2)]
        public int Age
        {
            get; set;
        }
    }

This is the derived class:

[ProtoContract]
    public class SubClass1 : BaseClass
    {
        [ProtoMember(3)]
        public string Town
        {
            get; set;
        }

        [ProtoMember(4)]
        public Sex Sex
        {
            get; set;
        }
    }

This is the code to serialize and deserialize (taken directly from the Getting Started Guide

var person = new SubClass1 { Age = 25, Name = "Fred", Town = "Denbigh", Sex = Sex.Female };

            using (var file = File.Create(filename))
            {
                Serializer.Serialize(file, person);
            }

and de -serialize:

SubClass1 newPerson;
            using (var file = File.OpenRead(filename))
            {
                newPerson = Serializer.Deserialize<SubClass1>(file);
            }

            MessageBox.Show(newPerson.Name + 
                " : " + newPerson.Town + 
                " : " + newPerson.Age.ToString() + 
                " : " + newPerson.Sex);

The result is " : Denbigh : 0 : Female"

Somehow the values from the base class properties are not being serialized? I originally tested it with the ProtoMember indices for the derived class as 1, 2. I kind of thought that would not work so went for 3, 4. It seems to make no difference. In my paranoia I ran the same test using the standard NET binary serializer and got the expected result: "Fred : Denbigh : 25 : Female"

What am I missing please?

Answer

wal picture wal · Oct 20, 2012

You need to use the ProtoInclude attribute on your base class:

[ProtoContract]
[ProtoInclude(500, typeof(SubClass1 ))]
public class BaseClass
{

The id arg (500 in the above example) should be unique to that class. See this article for more information