协议缓冲区是否支持具有共享引用的对象图的序列化?
请观察以下简单程序(基于 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 实现中的错误,还是协议缓冲区根本不支持具有共享引用的对象图?
谢谢。
Please, observe the following simple program (based on the example from the protobuf-net project 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));
}
}
}
The second assertion fails. Is this a bug in the protobuf-net implementation or is it that protocol buffers simply does not support object graphs with shared references?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
协议缓冲区本身不支持这一点 - 所以不,这不是一个错误。事实上,
XmlSerializer
和DataContractSerializer
* 会执行相同的操作(JavaScriptSerializer
和 JSON.NET 可能也会这样做)。然而,这是一个常见的请求,所以这个在 protobuf-net v2 中得到支持(基本上:我作弊)。只需将其更改为:(
并使用我在大约 5 分钟内上传的 v2 dll,或从代码构建)
*=caveat:
DataContractSerializer
确实 支持引用,但是仅当您使用特定的构造函数时;默认情况下它是禁用的protocol-buffers itself does not support this - so no, it is not a bug. Indeed,
XmlSerializer
andDataContractSerializer
* would do the same (and probably so wouldJavaScriptSerializer
and JSON.NET).However, it is a common request, so this is supported in protobuf-net v2 (basically: I cheat). Just change it to:
(and use the v2 dll that I'm uploading in about 5 minutes, or build from code)
*=caveat:
DataContractSerializer
does support references, but only if you use a specific constructor; it is disabled by default