2011-12-22 11 views
1

asmx WebサービスのWebMethodの結果としてオブジェクトを返すときにTエラーのオブジェクトをシリアル化する際に循環参照が検出されました。カスタムEqualsメソッドおよびGetHashCodeメソッドを使用してオブジェクトをシリアル化するときの循環参照エラー

クラスTからEqualsとGetHashCodeを削除すると、問題がなくなります。 私は循環参照を持たないので、循環参照がオブジェクトを比較することによって循環参照を検出し、それらが同等であれば円があると考えるように見えます。

もちろん、多くの人と同じように、Equalsクラスと別のクラスを定義して、多くの人が同じようにデータをコピーできますが、1つのクラスでdocode smellsのいずれかです。

私は、Equals、GetHashCodeを定義してそれを保つために、Serializableとしたいと考えています。どうやって ?

+0

OnSerializingおよびOnSerialized属性は、直列化の開始/終了時にフラグを設定し、メソッドの動作を無効または有効にするのに役立ちますが、WebMethodsの結果SOAP/Xmlシリアライザでは機能しません。 – alpav

+1

問題を説明する小さくて簡単な例を教えてください。この問題を引き起こす 'Equals'と' GetHashCode'実装を含めてください。 –

+0

また、ASMX Webサービスを使用している場合、 '[Serializable]'はまったく重要ではありません。 –

答えて

0

1つの方法は、OnSerializingメソッドを定義し、すべてのクラスでそのメソッドを実装して、適格な子に対して呼び出すことを、シリアル化に関係するすべてのクラスを継承することです。また、falseをデフォルトとして持つすべてのクラスにprivate boolメンバーをシリアライズし、OnSerializing内でtrueに設定します。それはルートでそれを呼び出すことができ、すべてのリーフまですべてのシリアライズ可能なノードに伝播することができます。

WebMethodから直列化可能なreturnValueを返す前に、returnValue.OnSerializing()を呼び出してください。

あなたがオーバーライドするたびに最初の行を等しいGetHashCodeメソッドの最初の行は、道の右OnSerializing呼び出すことにより、Webメソッドから戻る前に、あなたが等しく、GetHashCodeメソッドのカスタマイズを無効にするには、ツリー全体をマークif(Serializing)return base.GetHashCode();

する必要があり、if(Serializing)return base.Equals(obj);でなければなりません。

(たとえばディスクに保存して戻すなど)シリアル化の後に何かを行う必要がある場合は、OnSerializedを定義し、同じ方法でツリーに伝播して、シリアライズフラグをfalseに設定します。

もちろん、可能であれば、すべてのシリアライズ可能オブジェクトをインターフェイスではなく1つのクラスから継承し、すべてのシリアライズ可能なクラスの実装オーバーヘッドを減らすためにそこにすべてを実装します。

1

私はトラブルの根底に下ろしましょう。 私は同じ問題があったので。

私は、問題がGetHashCodeメソッドではなくEqualsメソッドで見つかったことを認識しました。

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" -methodを実行した場合、何が起こるでしょうか? InvalidOperationException、メッセージタイプTのオブジェクトのシリアル化中に循環参照が検出されました。

XmlSerializerは、XMLドキュメントに子オブジェクトと同じオブジェクトを追加しないようにします。これはサークルになるためです。 "これは同じオブジェクトです"をチェックする方法は、GetHashCodeメソッドとEqualsメソッドを使用してオブジェクトの等価性をチェックする方法です。

例では、これらのオブジェクトは異なるインスタンスに移行し、XmlSerializerは「メモリ内のインスタンス」をチェックしませんが、GetHashCodeとEqualsという既知のメソッドを使用します。

だから、あなたはルートにこの問題を回避するために、あなたのクラスやメソッドの実装を改善する方法

は考えて...あなたはは、等しい方法

それとももっと自分の実装方法を考えますトラブルの詳細。 ;-)

関連する問題