web-dev-qa-db-ja.com

ISerializableインターフェイスのポイントは何ですか?

そのインターフェイスを持たないクラスをシリアル化できるように思えるので、その目的がわかりません。

49
leora

ISerializableは、通常BinaryFormatter(およびおそらくリモート処理の目的)のために、カスタムバイナリシリアル化を提供するために使用されます。それなしでは、フィールドを使用します。

  • 非効率的な;実行時の効率化のためだけに使用されるが、シリアル化のために削除できるフィールドがある場合(たとえば、辞書はシリアル化されると異なるように見える場合があります)
  • 非効率的な;必要なフィールドであっても、多くの追加のメタデータを含める必要があるため
  • 無効; シリアル化できないフィールドがある場合(イベントデリゲートなど。ただし、[NonSerialized]
  • 脆い;シリアル化はfieldの名前にバインドされました-しかし、フィールドは実装の詳細を意味するものです。 難読化、シリアル化、および自動的に実装されるプロパティ も参照してください

ISerializableを実装することにより、独自のバイナリシリアル化メカニズムを提供できます。これに相当するxmlは、IXmlSerializableなどで使用されるXmlSerializerです。

DTOの目的には、BinaryFormatterを避ける必要があります-xml(XmlSerializerまたはDataContractSerializer経由)やjsonのようなものは、プロトコルバッファのようなクロスプラットフォームフォーマットと同様に適切です。

完全を期すために、protobuf-netにはISerializableのフックが含まれています(多くのコードを記述せずに移植可能なバイナリ形式を使用できるようにします)が、とにかくBinaryFormatterは最初の選択肢ではありません。

65
Marc Gravell

クラスは、次の2つの方法のいずれかで.NETでシリアル化できます。

  1. クラスをSerializableAttributeでマークし、NonSerializedでシリアル化する必要がないしないすべてのフィールドを装飾する属性。 (Marc Gravellが指摘しているように、BinaryFormatterオブジェクトは通常ISerializableオブジェクトをフォーマットするために使用されるクラスであり、特に指定がない限り、すべてのフィールドを自動的にシリアル化します。)
  2. 完全なカスタムシリアル化のためのISerializableインターフェイスの実装。

前者は、宣言を属性でマークするだけなので簡単に使用できますが、その力には限界があります。後者の場合、柔軟性が向上しますが、実装にかなりの労力がかかります。どちらを使用するかは、コンテキストに完全に依存します。

後者(ISerializable)とその使用に関しては、インターフェイスの MSDNページ から引用しました。

シリアル化される可能性のあるクラスは、SerializableAttributeでマークする必要があります。クラスがそのシリアル化プロセスを制御する必要がある場合、ISerializableインターフェイスを実装できます。 Formatterは、シリアル化時にGetObjectDataを呼び出し、指定されたSerializationInfoにオブジェクトを表すために必要なすべてのデータを設定します。 Formatterは、グラフ内のオブジェクトのタイプでSerializationInfoを作成します。プロキシを自分で送信する必要があるオブジェクトは、SerializationInfoのFullTypeNameメソッドとAssemblyNameメソッドを使用して、送信される情報を変更できます。

クラス継承の場合、ISerializableを実装する基本クラスから派生したクラスをシリアル化することができます。この場合、派生クラスは、GetObjectDataの実装内でGetObjectDataの基本クラス実装を呼び出す必要があります。それ以外の場合、基本クラスからのデータはシリアル化されません。

9
Noldorin

ISerializableを使用すると、バイナリシリアル化を行うときにシリアル化を引き継ぐカスタムメソッドをオブジェクトに記述して、BinaryFormatterが使用するデフォルトのアプローチとは異なる方法でオブジェクトをシリアル化できます。

つまり、デフォルトのアプローチでオブジェクトをシリアル化する方法とは異なる方法でオブジェクトをシリアル化する場合、完全に制御するためにISerializableを実装できます。 ISerializableと連携して、実装する必要があるカスタムコンストラクターもあります。

XmlSerializationはもちろんプロパティのみを使用し、ISerializableはXMLシリアル化とは関係ありません。

コメントをしてくれたマークとポップに感謝します。最初の答えは少し急ぎました。

オブジェクトを「トランスポータブル」にするには、シリアル化する必要があります。たとえば、.NET RemotingまたはWebサービスを使用してオブジェクトデータを転送する場合は、オブジェクトデータをシリアル化するメソッドを提供する必要があり、オブジェクトインスタンスをオブジェクトの忠実度の高い表現を表すトランスポータブル形式に減らす必要があります。

次に、シリアル化された表現を取得して、別のマシンなどの別のコンテキストに転送し、元のオブジェクトを再構築します。

ISerializableインターフェイスを実装する場合、クラスは、インターフェイスに含まれるGetObjectDataメソッドと、SerializationInfoのインスタンスとStreamingContextの2つのパラメーターを受け入れるように特化した専用コンストラクターを提供する必要があります。

クラスでオブジェクトの状態をきめ細かく制御する必要がない場合は、[Serializable]属性。シリアル化プロセスをさらに制御する必要があるクラスは、ISerializableインターフェイスを実装できます。

3
splattne