6

I've googled a bit for this now, but haven't been able to determine if protobuf-net or protobuf in general supports forward compatibility in the following sense:

An older version of the object deserializes a new version of the object with a new field, but preserves this field when serializing it back, so the new version of the object doesn't lose the value.

Is this possible with protobuf's?

Many Thanks

Damian
  • 61
  • 1

1 Answers1

7

Yes; round-tripping unknown data is supported by most protobuf implementations. Since you specifically tagged - if you are using code-first (i.e. writing classes by hand, which is pretty common with protobuf-net), then you need to provide support for this explicitly. The easiest way to do this is to inherit Extensible. The following shows successful round-trip via a type that knows nothing of the field:

using System;
using System.IO;
using ProtoBuf;

[ProtoContract]
class Foo
{
    [ProtoMember(1)]
    public int X { get;set; }
    [ProtoMember(2)]
    public int Y { get;set; }
}
[ProtoContract]
class Bar : Extensible
{
    [ProtoMember(1)]
    public int A { get;set; } // if declared, needs to be compatible

    // note we don't have a declared field 2 here
}
static class Program
{
    static void Main()
    {
        Foo orig = new Foo { X = 123, Y = 456 }, clone;
        Bar bar;
        using(var ms = new MemoryStream())
        {
            Serializer.Serialize(ms, orig);
            ms.Position = 0;
            bar = Serializer.Deserialize<Bar>(ms);

            Console.WriteLine(bar.A); // 123 // query known data
            int b = Extensible.GetValue<int>(bar, 2); // query unknown data
            Console.WriteLine(b); // 456
        }
        using (var ms = new MemoryStream())
        {
            Serializer.Serialize(ms, bar);
            ms.Position = 0;
            clone = Serializer.Deserialize<Foo>(ms);
        }
        Console.WriteLine(clone.X); // 123
        Console.WriteLine(clone.Y); // 456
    }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900