2010-04-10 53 views
1

我有問題使用protobuf網反序列化ORM生成的實體的某些Guid屬性。這裏是一個簡化的代碼示例(重現場景的大多數元素,但不重現行爲;我不能公開我們的內部實體,所以我正在尋找線索來解決這個異常)。假設我有一個類Account,其中AccountID只讀guid和一個AccountName讀寫字符串。我序列化&立即反序列化一個克隆。protobuf網絡:不正確的線型異常反序列化Guid屬性

反序列化在反序列化時拋出Incorrect wire-type deserializing Guid異常。

這裏的用法示例...

 Account acct = new Account() { AccountName = "Bob's Checking" }; 
     Debug.WriteLine(acct.AccountID.ToString()); 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      ProtoBuf.Serializer.Serialize<Account>(ms, acct); 
      Debug.WriteLine(Encoding.UTF8.GetString(ms.GetBuffer())); 
      ms.Position = 0; 
      Account clone = ProtoBuf.Serializer.Deserialize<Account>(ms); 
      Debug.WriteLine(clone.AccountID.ToString()); 
     } 

而且這裏有一個例子ORM'd類(簡化,但演示我能想到的相關語義)。使用shell遊戲通過公開後臺字段來反序列化只讀屬性(「不能寫入」本質上變成了「不應該寫入」,但我們可以掃描代碼以分配給這些字段的實例,所以黑客適用於我們的目的)。

再次,這是而不是重現異常行爲;我在尋找線索,以什麼可能

[DataContract()] 
[Serializable()] 
public partial class Account 
{ 
    public Account() 
    { 
     _accountID = Guid.NewGuid(); 
    } 
    [XmlAttribute("AccountID")] 
    [DataMember(Name = "AccountID", Order = 1)] 
    public Guid _accountID; 

    /// <summary> 
    /// A read-only property; XML, JSON and DataContract serializers all seem 
    /// to correctly recognize the public backing field when deserializing: 
    /// </summary> 
    [IgnoreDataMember] 
    [XmlIgnore] 
    public Guid AccountID 
    { 
     get { return this._accountID; } 
    } 

    [IgnoreDataMember] 
    protected string _accountName; 

    [DataMember(Name = "AccountName", Order = 2)] 
    [XmlAttribute] 
    public string AccountName 
    { 
     get { return this._accountName; } 
     set { this._accountName = value; } 
    } 
} 

XML,JSON和DataContract序列化似乎都序列化/反序列化這些對象圖就好了,所以屬性設置基本的工作原理。我試過protobuf網與列表與單個實例,不同的前綴樣式等,但仍然總是得到'不正確的線型... Guid'異常時反序列化。

所以具體的問題是,有沒有任何已知的解釋/解決方法呢?我無法追蹤哪些情況(在真實的代碼中,但不是例子中)可能導致它。

我們希望不必直接在實體層創建protobuf依賴;如果是這樣的話,我們可能會創建所有具有protobuf屬性的公共屬性的代理DTO實體。 (這是我對所有聲明式序列化模型的一個主觀問題;它是一個無處不在的模式&我明白爲什麼它會出現,但是IMO,如果我們可以讓一個人登上月球,那麼「正常」應該是有對象和序列化契約去耦合;-))

謝謝!

+0

@Paul - 只是一個基於你的調試線的隨機想法...你是否將二進制文件視爲字符串?這不會工作:http://marcgravell.blogspot.com/2010/03/binary-data-and-strings.html – 2010-04-10 17:28:58

+0

@marc - 合理的檢查,但不是,字符串輸出只是一個快速的視覺三角洲。答案線程中的其他註釋。謝謝! – 2010-04-12 18:11:59

回答

1

同意,你不應該需要一個明確的依賴 - DataMember是好的。 protobuf-net使用相同的邏輯忽略等。您如何/在哪裏存儲數據?根據我的經驗,這最常見的原因是人們用不同的數據覆蓋緩衝區(或文件),而不是截斷它(在流的末尾留下垃圾),as discussed here。這與你的場景有關嗎?

+0

+1,絕對是一個很好的搜索路徑。 嘗試設置ms.Capacity = Convert.ToInt32(ms.Length)(爲什麼.Capacity int&.Length長,BTW?);仍然擊中相同的「不正確的線型反序列化Guid」異常。 – 2010-04-10 07:15:23

+0

@Paul - 我沒有寫'MemoryStream' ;-p重新發現導線類型問題 - 是否有一個可重複的例子? – 2010-04-10 09:02:42

+0

@保羅 - 這不是重要的「能力」;它是'長度'。如果你正在重寫一個'MemoryStream',你必須*截斷它(之前或之後無關緊要)。問題(覆寫)是如果你寫了第一個對象,並且它是(比如說)254字節,那麼你將該位置設置爲0並且重寫第二個對象(比如說)120字節,則該流是* *仍然* 254字節長。最後的134個字節現在是垃圾。查看引用問題中的SetLength()點。 – 2010-04-10 09:07:48