2013-04-29 66 views
2

我試圖序列化使用protobuf網庫的對象的集合。我遇到了一個問題,即集合中的頂級對象沒有被設置爲圖形中的引用,因此當它們在序列化的子節點中被進一步引用時,它們將被重新序列化並在此時創建爲引用。有沒有辦法讓頂級對象被序列化爲引用?我讀過幾篇似乎表明protobuf-net支持這一點的衝突帖子,而其他帖子似乎建議圍繞頂層對象創建一個包裝以啓用此行爲。謝謝...Protobuf網絡根級別列表序列化參考

這裏是示例程序顯示我的問題。正如你所看到的,引用不相等。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using ProtoBuf; 

namespace ProtoBufTest 
{ 
    [ProtoContract(AsReferenceDefault=true)] 
    public class Foo 
    { 
     [ProtoMember(1, AsReference=true)] 
     public FooChild Child; 

     [ProtoMember(2)] 
     public Guid Id; 
    } 

    [ProtoContract] 
    public class FooChild 
    { 
     [ProtoMember(1, AsReference=true)] 
     public Foo Parent; 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Foo> foos = new List<Foo>() 
      { 
       new Foo() { Child = new FooChild(), Id = Guid.NewGuid() } 
      }; 

      foos[0].Child.Parent = foos[0]; 

      var clone = Serializer.DeepClone(foos); 

      Console.WriteLine(ReferenceEquals(clone[0], clone[0].Child.Parent)); 
      Console.WriteLine(clone[0].Id == clone[0].Child.Parent.Id); 
     } 
    } 
} 

回答

0

如果你實際上意味着根對象(即傳入Serialize的對象),那麼就應該簡單的工作,例如:

using ProtoBuf; 
using System; 
[ProtoContract] 
public class Foo 
{ 
    [ProtoMember(1)] 
    public Bar Bar { get; set; } 
} 
[ProtoContract] 
public class Bar 
{ 
    [ProtoMember(1, AsReference = true)] 
    public Foo Foo { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     var foo = new Foo { Bar = new Bar() }; 
     foo.Bar.Foo = foo; 
     var clone = Serializer.DeepClone(foo); 

     // writes: True 
     Console.WriteLine(ReferenceEquals(clone, clone.Bar.Foo)); 
    } 
} 

如果不是工作,那麼我懷疑它實際上並不是根目錄,但它只是圖形中的某些東西(但非根目錄) - 在這種情況下,添加AsReference=true應該修復它。

注意,我也是一個過期的公開發布,但源代碼現在已經在合同層面表達這更好的支持 - 這將被包含在未來的版本。例如(從內存工作在這裏):

[ProtoContract(AsReferenceDefault=true)] 
public class Foo 
{ 
    [ProtoMember(1)] 
    public Bar Bar { get; set; } 
} 

這就隱含的假設是任何Foo成員應序列作爲參考除非它們被明確禁用(AsReference=false)。

+0

非常感謝您的快速反應 - 順便說一句,你的圖書館已經很大了我們的應用程序,並正在爲我們所有的WCF服務,這些少數的例外。當我看到我沒有問得很好時,讓我澄清一下我的問題。我試圖序列化的根對象是IList - Foo標有AsReferenceDefault = true ProtoContract屬性,但List中的那些Foo對象似乎不被視爲引用。 – Nick 2013-04-29 17:33:23

+0

@ user1863798你可以提供一個簡短但完整的例子,我可以使用repro? (並作爲一個集成測試,以確保它在調整後保持工作狀態) – 2013-04-29 17:34:35

+0

只需添加一個標籤以通知已添加的示例代碼即可。 – Nick 2013-04-29 19:35:50