Поддерживают ли буферы протокола сериализацию графов объектов с общими ссылками? - PullRequest
7 голосов
/ 19 мая 2011

Пожалуйста, обратите внимание на следующую простую программу (на примере примера из проекта protobuf-net v1 wiki):

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using ProtoBuf;

namespace HelloProtoBuf
{
  [ProtoContract]
  class Person
  {
    [ProtoMember(1)]
    public int Id { get; set; }
    [ProtoMember(2)]
    public string Name { get; set; }
    [ProtoMember(3)]
    public Address Address { get; set; }
  }
  [ProtoContract]
  class Address
  {
    [ProtoMember(1)]
    public string Line1 { get; set; }
    [ProtoMember(2)]
    public string Line2 { get; set; }
  }


  class Program
  {
    static void Main(string[] args)
    {
      var person = new Person
      {
        Id = 12345,
        Name = "Fred",
        Address = new Address
        {
          Line1 = "Flat 1",
          Line2 = "The Meadows"
        }
      };
      var person2 = new Person
      {
        Id = 4553,
        Name = "Nadya",
        Address = person.Address
      };
      var persons = new List<Person> { person, person2 };
      Debug.Assert(ReferenceEquals(persons[0].Address, persons[1].Address));

      using (var file = File.Create("persons.bin"))
      {
        Serializer.Serialize(file, persons);
      }
      List<Person> persons2;
      using (var file = File.OpenRead("persons.bin"))
      {
        persons2 = Serializer.Deserialize<List<Person>>(file);
      }
      Debug.Assert(ReferenceEquals(persons2[0].Address, persons2[1].Address));
    }
  }
}

Второе утверждение не выполняется.Это ошибка в реализации protobuf-net или буферы протокола просто не поддерживают графы объектов с общими ссылками?

Спасибо.

1 Ответ

9 голосов
/ 19 мая 2011

protocol-buffers сама не поддерживает это - так что нет, это не ошибка.Действительно, XmlSerializer и DataContractSerializer* будут делать то же самое (и, вероятно, так же, как и JavaScriptSerializer и JSON.NET).

Однако это общий запрос, поэтому этот поддерживается вprotobuf-net v2 (в основном: я обманываю).Просто измените его на:

    [ProtoMember(3, AsReference=true)]
    public Address Address { get; set; }

(и используйте библиотеку v2, которую я загружаю примерно за 5 минут, или создайте код)


* = предостережение: DataContractSerializer поддерживает ссылки, но только если вы используете определенный конструктор;по умолчанию отключено

...