Protobuf-сеть, сохраняя будущие поля
Сейчас я немного погуглил, но не смог определить, поддерживает ли protobuf-net или protobuf в целом прямую совместимость в следующем смысле:
Старая версия объекта десериализует новую версию объекта с новым полем, но сохраняет его при повторной сериализации, поэтому новая версия объекта не теряет значение.
Возможно ли это с протобуфами?
Большое спасибо
1 ответ
Да; Обращение неизвестных данных в обходе поддерживается большинством реализаций protobuf. Поскольку вы специально пометили protobuf-net - если вы используете код вначале (т.е. пишете классы вручную, что довольно часто встречается в protobuf-net), то вам необходимо явно поддержать это. Самый простой способ сделать это - наследовать Extensible
, Следующее показывает успешное прохождение туда и обратно через тип, который ничего не знает о поле:
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
}
}