3

バイナリ シリアル化を使用してディープ クローンされたデータ オブジェクトがあります。このデータ オブジェクトは、PriceChanged などのプロパティ変更イベントをサポートします。

PriceChanged にハンドラーを追加したとします。コードが PriceChanged をシリアル化しようとすると、ハンドラーがシリアル化可能としてマークされていないという例外がスローされます。

私の代替案:

  • シリアル化の前にイベントからすべてのハンドラーを簡単に削除することはできません
  • すべてのハンドラーの依存関係も再帰的にマークする必要があるため、ハンドラーをシリアル化可能としてマークしたくありません。
  • PriceChanged を NonSerialized としてマークしたくありません。ハンドラーを持つ可能性のあるこのようなイベントが数十あります。EDIT:これができないもう1つの理由は、データクラス(したがってイベント)が生成され、生成コードを直接制御できないためです。理想的には、生成コードはすべてのイベントを NonSerialized としてマークするだけです。
  • 理想的には、.NET がその時点でオブジェクト グラフをたどるのをやめて、それを「リーフ」にすることを望みます。では、.NET でクラス全体を NonSerialized としてマークできないのはなぜでしょうか?

--

最終的に、ハンドラーに ISerializable を実装させ、シリアル化コンストラクター/ GetDataObject メソッドで何もしないことで、この問題を回避しました。ただし、ハンドラーは依然としてシリアル化されており、すべての依存関係が null に設定されているため、それも考慮する必要がありました。

クラス全体のシリアル化を防ぐより良い方法はありますか? つまり、null 依存関係を考慮する必要がないものですか?

4

2 に答える 2

4

私はこのアプローチに反対する傾向がありますが (イベントの数に関係なく、単純にイベントを NonSerialized としてマークします)、シリアライゼーション サロゲートを使用してこれを行うことができます。

アイデアは、ISerializationSurrogate を実装するオブジェクトを作成し、基本的に既に行っていることを行うということです。GetObjectData および SetObjectData メソッドでは何もしません。違いは、デリゲートを含むクラスではなく、デリゲートのシリアル化をカスタマイズすることです。

何かのようなもの:

class DelegateSerializationSurrogate : ISerializationSurrogate {
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
    }
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
        return null;
    }
}

次に、この MSDN コラムで概説されている手順を使用して、これをフォーマッタに登録します。次に、フォーマッタがデリゲートに遭遇するたびに、デリゲートを直接シリアル化する代わりにサロゲートを使用します。

于 2010-03-18T03:44:01.370 に答える
2

...何十ものイベントがあります...

個人的には、シリアル化されていないマーカーを追加するだけです。これは、フィールドのようなイベントの場合、次の方法で最も簡単に実行できます。

[field: NonSerialized]
public event SomeEventType SomeEventName;

(手動のバッキングデリゲートを追加する必要はありません)

シリアル化の要件は正確には何ですか?BinaryFormatter多くの点で、シリアライザーの中で最も友好的ではありません。イベントへの影響は少し醜く、保存すると非常に壊れやすくなります(IMOは、保存ではなく、輸送にのみ適しています)。

でも; 最も一般的な「ディープクローン」シナリオをサポートする優れた代替案はたくさんあります。

  • XmlSerializer(ただし、パブリックメンバーに限定されます)
  • DataContractSerializer/NetDataContractSerializer
  • protobuf-net(Serializer.DeepCloneこの目的のために含まれます)

(これらのシリアル化サポートのほとんどでは、追加の属性が必要になるため、最初に属性を追加するのと大差ないことに注意してください[NonSerialized]!)

于 2010-03-18T05:14:06.920 に答える