1

を暗示する属性を作成しようとしましたが、このクラスが封印[Serializable]されていることに気付きました。SerializableAttribute

Javaでは、インターフェースMyInterfaceから継承されるインターフェース(たとえば)を作成することが可能であったSerializableため、のすべてのサブクラスMyInterfaceもシリアライズ可能であり、そのサブサブクラスもシリアライズ可能です。

ORMを作成していて、顧客にエンティティクラスに注釈を付けてもらいたいとしましょう。[DatabaseEntity]ただし、エンティティがシリアル化可能であることを確認するために、クラスを[Serializable]非常にコンパクトできれいに見えない余分なもので属性付けするように依頼する必要もあります。

SerializableAttributeクラスがなぜでsealedあり、なぜ持っているのか疑問に思ってInherited=falseいます。これは、明示的に指定されていない限り、シリアル化可能なクラスのサブクラスがシリアル化できないことを意味します。これらのデザインの選択の背後にある動機は何ですか?

4

4 に答える 4

4

SerializableAttribute は、BinaryFormatter によってのみ使用されます。独自のシリアライザーを作成している場合は、心配する必要はありません。

キーワードは、sealed属性に関連付けられたクラスではなく、属性に適用されます。SerializableAttribute をサブクラス化できないと言っています。

BinaryFormatterオプトイン モデルを使用します。すべてのクラス (またはサブクラス) は、シリアライズ可能であることを指定する必要があります。これが が使用される理由Inherited=falseです。

于 2012-11-09T22:38:01.860 に答える
1

Microsoft によると、すべての.Net 属性を封印することをお勧めします。

.NET Framework クラス ライブラリには、カスタム属性を取得するためのメソッドが用意されています。デフォルトでは、これらのメソッドは属性継承階層を検索します。たとえばSystem.Attribute.GetCustomAttribute、指定された属性タイプ、または指定された属性タイプを拡張する任意の属性タイプを検索します。属性を封印すると、継承階層を介した検索が不要になり、パフォーマンスが向上します。【私のこだわり】

.Net[Serializable]リフレクションが属性をチェックする方が速いため、封印されています。コストは、継承および拡張できないことですSerializableAttribute

必要に応じて、独自の封印されていない属性を作成できます (ただし、コード分析の警告が表示されます)。

これは、属性が適用されるクラスの継承で属性がどのように使用されるかを少し混乱させます。例を使用するのがおそらく最善です:

[Serializable]
public class A
{
    public int SimpleSerialisableProperty { get; set;}
}

public class B : A
{
    public C ComplexReferenceProperty { get; set; }
}

[Serializable]
public class D : A
{
    public bool AnotherSerialisableProperty { get; set;}
}

あなたは理由SerializableAttribute.Inherited = falseを尋ねましたが、これが理由です:

  • クラスAは としてマークされて[Serializable]おり、そうです。

  • ただし、クラスはシリアル化できないプロパティでそれをB継承および拡張します。A.Net がシリアル化しようとBすると、エラーが発生します。

  • これInherited = falseは.Netに、それを継承するすべてのクラスがシリアライズ可能になるわけではないという理由だけでAマークされていることを伝えます。[Serializable]

  • クラスはD継承Aされ、シリアライズ可能になったため、独自の[Serializable]属性を取得します。

最後に、デザイン属性に関しては、動作を拡張する優れた方法です(プロパティ グリッドの優れた UI エディターなど)。しかし、彼らはそれを強制するのがひどいです。顧客に特定の方法でエンティティ クラスを実装してもらう必要がある場合は、abstract基本クラスまたは を使用するinterface方がはるかに優れています。[Serializable]それを属性にすると、基本的に、それがどちらの方法でも処理できるオプションであることを彼らに知らせることになります。

于 2013-01-22T10:49:00.817 に答える
0

シリアル化は魔法のようなものではなく、オブジェクトをシリアル化するために属性は必要ありません。これは、クラスのプロパティとフィールドをストリームに書き込むプロセスです(属性は、オブジェクトの出力中の動作方法に関するシリアライザーへのディレクティブにすぎません)。

を含むすべての属性を完全に無視するこの過度に単純化されたシリアライザーコードを参照してくださいNonSerializable

object obj = yourObject;

var props = obj.GetType()
               .GetProperties()
               .ToDictionary(p => p.Name, p => p.GetValue(obj, null));

string serializedText = String.Join("\n",
              props.Select(kv => kv.Key + "=" + kv.Value ?? kv.Value.ToString()));

たとえば、上記のコードは次のようになります

IsEmpty=False
X=3
Y=5

にとってobject obj = new Point(3,5);

デシリアライズプロセスでは、これらの値を読み取り、それに応じてプロパティを元に戻します。

于 2012-11-09T22:51:33.590 に答える
-2

シリアル化するクラスの上に [Serializable] 属性を配置します。シリアル化はオプトイン プロセスです。シリアル化するクラスごとに手動で行う必要があります。他にもたくさんのキーワードがあります。

于 2012-11-09T22:39:52.973 に答える