2011-12-22 36 views
1

我得到在返回我的對象​​作爲我的ASMX web服務的WebMethod的結果,當串行化類型T誤差的對象中檢測到循環引用。循環引用錯誤的Equals和GetHashCode方法

如果我從類T中刪除Equals和GetHashCode,問題就消失了。 我沒有任何循環引用,所以它看起來像序列化通過比較對象來檢測循環引用,如果它們相等,它認爲有圓圈。

當然,我可以用Equals和另一個類來定義一個用於序列化的類,就像許多人一樣,然後將數據從一個複製到另一個,但我希望能夠在一個類中完成,以避免parallel class hierarchiescode smells之一。

我希望能夠定義Equals,GetHashCode並保持它Serializable。怎麼樣 ?

+0

在序列化開始/結束時,OnSerializing和OnSerialized屬性可以幫助設置標誌和禁用/啓用方法行爲,但對於WebMethods結果SOAP/Xml序列化程序無效。 – alpav 2011-12-22 21:46:50

+1

你能舉一個簡單的例子來說明問題嗎?請包括導致問題的'Equals'和'GetHashCode'實現。 – 2011-12-23 04:18:53

+0

另外,如果您使用的是ASMX Web服務,那麼'[Serializable]'完全不重要。 – 2011-12-23 04:19:21

回答

0

一種方法是從一個接口繼承序列化中涉及的每個類,該接口定義OnSerializing方法並在每個類中實現該方法以針對符合條件的子級調用該方法。還要在每個類中使用false作爲默認序列化私有bool成員,並在OnSerializing中將其設置爲true。這將允許在根上調用它並傳播到所有可串行化節點,直到每一片葉子。

在從WebMethod返回可串行返回值之前調用returnValue.OnSerializing()。

每次你重載equals第一行應該是if(Serializing)return base.Equals(obj);,在GetHashCode的第一行應該是if(Serializing)return base.GetHashCode();

這樣的權利,通過調用OnSerializing你的WebMethod返回之前標誌着整個樹禁用的Equals和GetHashCode的定製。

如果您需要在序列化之後執行某些操作(例如保存在磁盤上然後返回),那麼定義OnSerialized並通過樹來傳播,以將Serialize標誌設置爲false。

當然,如果可能,只需從一個類而不是接口繼承所有可序列化的對象,並在那裏實現所有內容以減少每個可序列化類中的實現開銷。

1

讓我回到麻煩的根源。 因爲我有同樣的問題。

我意識到,問題沒有在GetHashCode方法中找到,而是在Equals-method中找到。

XmlSerializer拋出這種異常的最重要原因是由於XML文檔的結構和XmlSerializer內部的「等同機制」。

例如:

private XmlSerializer serializer; 

public void TryToSerialize(TextWriter output) 
{ 
    MyObject instance = new MyObject(); 
    instance.Key = 101; 
    instance.SomeValue = "Some value"; 
    instance.Child = new MyObject(); 
    instance.Child.Key = 101; 
    instance.Child.SomeValue = "Another value"; 

    serializer.Serialize(output, instance); 
} 

和我如何實現的GetHashCode,方法和equals法?

像這樣:

public overrides int GetHashCode() 
{ 
    return this.Key.GetHashCode(); 
} 

public overrides bool Equals(object obj) 
{ 
    if(obj == null) return false; 

    MyObject other = obj as MyObject; 
    if(other == null) return false; 

    return this.Key.Equals(other.Key); 
} 

而且會發生什麼,如果我運行 「TryToSerialize」 - 方法? 我將得到一個InvalidOperationException與消息在序列化T類型的對象時檢測到循環引用。

在進行serilization時,XmlSerializer會嘗試避免將相同的對象作爲子項添加到XML文檔中,因爲這會導致出現一個圓圈。 但是,檢查「這是同一個對象」的方法是使用GetHashCode-method和Equals-method來設計它們的目的 - 檢查對象的相等性。

在我們的例子中,這些對象migth是不同的實例,而XmlSerializer不檢查「內存中的實例」,而是使用它所知道的方法--GetHashCode和Equals。

所以,想想你如何實現你的等號方法

或者更好的...

想想如何改進你的類和方法的實施,以避免這個問題,在根的麻煩。 ;-)

相關問題