「NonSerialized」属性をクラス レベルで使用できないのはなぜですか?クラスのシリアル化を防ぐにはどうすればよいですか?
-
20-09-2019 - |
質問
バイナリ シリアル化を使用してディープ クローン作成されたデータ オブジェクトがあります。このデータ オブジェクトは、PriceChanged などのプロパティ変更イベントをサポートします。
PriceChanged にハンドラーをアタッチしたとします。コードが PriceChanged をシリアル化しようとすると、ハンドラーがシリアル化可能としてマークされていないという例外がスローされます。
私の代替案:
- シリアル化前にイベントからすべてのハンドラーを簡単に削除できません
- すべてのハンドラーの依存関係も再帰的にマークする必要があるため、ハンドラーをシリアル化可能としてマークしたくありません。
- PriceChanged を NonSerialized としてマークしたくありません。潜在的にハンドラーを持つ可能性のあるこのようなイベントが数十個あります。編集:これを実行できないもう 1 つの理由は、データ クラス (したがってイベント) が生成されるが、生成コードを直接制御できないためです。理想的には、生成コードはすべてのイベントを NonSerialized としてマークするだけです。
- 理想的には、.NET がその時点でオブジェクト グラフを下るのをやめて、それを「リーフ」にしたいと考えています。 では、なぜ .NET ではクラス全体を NonSerialized としてマークすることができないのでしょうか?
--
最終的に、ハンドラーに ISerializable を実装させ、シリアル化コンストラクター/GetDataObject メソッドでは何も行わないことで、この問題を回避しました。ただし、ハンドラーはすべての依存関係が null に設定されているだけでシリアル化されているため、それも考慮する必要がありました。
クラス全体のシリアル化を防ぐより良い方法はありますか? つまり、null 依存関係を考慮する必要がないものですか?
解決
私は(私は関係なく、そこにあるどのように多くの、NonSerializedなどのイベントをマークするだけでしょう)アプローチに同意しない傾向があるが、おそらく、シリアル化サロゲートを使用してこれを行うことができます。
GetObjectDataとSetObjectData方法では何も -アイデアは、あなたがISerializationSurrogateを実装し、基本的にはあなたがすでにやっていないしているものないオブジェクトを作成することです。違いは、あなたがデリゲートではなく、それを含むクラスのシリアル化をカスタマイズするだろうということです。
のような何かます:
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のコラムで概説した手順を使用してフォーマッタでこれを登録に。フォーマッタは、デリゲートに遭遇するたびに続いて、それが直接デリゲートをserializatingのではなく、サロゲートを使用します。
他のヒント
...何十ものイベントがあります...
個人的には、シリアル化されていないマーカーを追加するだけです。これは、フィールドのようなイベントの場合、次の方法で最も簡単に実行できます。
[field: NonSerialized]
public event SomeEventType SomeEventName;
(手動で補助デリゲートを追加する必要はありません)
シリアル化要件は正確には何ですか? BinaryFormatter
多くの点で、シリアライザーの中で最もフレンドリーではありません。イベントへの影響は少し醜く、保管すると非常にもろくなります (IMO では実際に保管には適しておらず、輸送にのみ適しています)。
しかし;最も一般的な「ディープ クローン」シナリオをサポートする優れた代替手段がたくさんあります。
XmlSerializer
(ただし一般会員に限ります)DataContractSerializer
/NetDataContractSerializer
- protobuf-net (これには、
Serializer.DeepClone
この目的のために)
(これらのシリアル化サポートのほとんどでは追加の属性が必要となるため、 [NonSerialized]
そもそも属性!)