协议缓冲区是不是支持具有共享引用的对象图的序列化?

Posted

技术标签:

【中文标题】协议缓冲区是不是支持具有共享引用的对象图的序列化?【英文标题】:Does protocol buffers support serialization of object graphs with shared references?协议缓冲区是否支持具有共享引用的对象图的序列化? 【发布时间】:2011-05-19 19:13:49 【问题描述】:

请注意以下简单程序(基于 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】:

protocol-buffers itself 不支持这个 - 所以不,这不是一个错误。事实上,XmlSerializerDataContractSerializer* 会做同样的事情(javascriptSerializer 和 JSON.NET 可能也会这样做)。

但是,这是一个常见的请求,所以 protobuf-net v2 支持(基本上:我作弊)。只需将其更改为:

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

(并使用我在大约 5 分钟内上传的 v2 dll,或从代码构建)


*=caveat:DataContractSerializer确实支持引用,但前提是您使用特定的构造函数;默认禁用

【讨论】:

是否可以通过命令式模型(RuntimeTypeModel)传达这些信息?问题是我的代理被归因于 DataContract/DataMember 以避免引用 protobuf-net。谢谢。 @mark - 是的; yourMetaType[3].AsReference = true;,其中3 是字段编号(DCS 用语中的Order=3 那么 Marc,这个图序列化在幕后是如何工作的?您是否为每个引用的对象创建隐藏的 int id(如代理主键),然后在加载时恢复它们? @Lone 是的,就是这样 - 仅适用于标记为此用法的关系 太棒了。本周末,我将尝试将它用于 Ludem Dare 的快速而肮脏的序列化程序 (ludumdare.com/compo/rules)。需要很多很棒的忍者工具,比如你在这里制作的那个!

以上是关于协议缓冲区是不是支持具有共享引用的对象图的序列化?的主要内容,如果未能解决你的问题,请参考以下文章

谷歌协议缓冲区是不是支持序列化前的大小计算?

iOS 网络 - Moya 和协议缓冲区序列化

是否可以使用协议缓冲区序列化 System.Object 对象列表

对象移动

协议缓冲区比序列化更好?

java 字符串处理