バージョン トレラントなシリアル化
.NET Framework のバージョン 1.0 および 1.1 では、あるバージョンのアプリケーションから次バージョンに移行しても再利用できる、シリアル化可能な型の作成に問題がありました。フィールドを追加して型を変更すると、次のような問題が発生することがありました。
以前のバージョンのアプリケーションは、元の型の新バージョンを逆シリアル化するように要求されると例外をスローする。
新しいバージョンのアプリケーションは、データの不足している以前のバージョンの型を逆シリアル化すると例外をスローする。
バージョン トレラントなシリアル化 (VTS : Version Tolerant Serialization) は、シリアル化可能な型を後からでも簡単に変更できるように .NET Framework 2.0 に導入された機能セットです。具体的には、VTS 機能は、SerializableAttribute 属性が適用されているクラスに対して使用可能です。VTS を使用すると、これらのクラスに対して、型の他のバージョンとの互換性を失うことなく、新しいフィールドを追加できます。実際に動作するサンプル アプリケーションについては、「シリアル化の複数バージョンに対応する技術サンプル」を参照してください。
VTS 機能は、BinaryFormatter を使用する場合に使用可能です。また、SoapFormatter を使用する場合は、外部データ トレランスを除くすべての機能も使用可能になります。シリアル化でこれらのクラスを使用する方法の詳細については、「バイナリ シリアル化」を参照してください。
![]() |
---|
BinaryFormatter に対する外部データ トレランス機能は、今後、.NET Framework 1.1 の更新プログラムとして提供される可能性があります。 |
機能の一覧
この機能セットの内容は次のとおりです。
外部データまたは予期しないデータに対するトレランス。これにより、新しいバージョンの型は以前のバージョンにデータを送信できます。
不足している省略可能なデータに対するトレランス。これにより、以前のバージョンは新しいバージョンにデータを送信できます。
シリアル化のコールバック。これにより、データが不足している場合でも、既定値をインテリジェントに設定できます。
この他にも、省略可能なフィールドが新たに追加されたときに宣言する機能があります。これは、OptionalFieldAttribute 属性の VersionAdded プロパティです。
次に、これらの各機能について詳しく説明します。
外部データまたは予期しないデータに対するトレランス
これまでは、逆シリアル化の実行中に外部データまたは予期しないデータが検出されると、必ず例外がスローされていました。VTS では、同じ状況で、例外がスローされるのではなく、外部データまたは予期しないデータはすべて無視されます。これにより、新しいバージョンの型 (新たにフィールドが追加されているバージョン) を使用するアプリケーションが、同じ型の以前のバージョンを必要とするアプリケーションに情報を送ることが可能になります。
次の例では、以前のアプリケーションが新しいバージョンを逆シリアル化する際、バージョン 2.0 の Address
クラスの CountryField
に含まれる追加データは無視されます。
// Version 1 of the Address class.
[Serializable]
public class Address
{
public string Street;
public string City;
}
// Version 2.0 of the Address class.
[Serializable]
public class Address
{
public string Street;
public string City;
// The older application ignores this data.
public string CountryField;
}
' Version 1 of the Address class.
<Serializable> _
Public Class Address
Public Street As String
Public City As String
End Class
' Version 2.0 of the Address class.
<Serializable> _
Public Class Address
Public Street As String
Public City As String
' The older application ignores this data.
Public CountryField As String
End Class
不足しているデータに対するトレランス
OptionalFieldAttribute 属性をフィールドに適用することで、このフィールドを省略可能としてマークできます。逆シリアル化の実行中に省略可能なデータが不足していることが検出されても、シリアル化エンジンはデータの不足を無視し、例外をスローしません。そのため、以前のバージョンの型を必要とするアプリケーションでも、同じ型の新しいバージョンを必要とするアプリケーションにデータを送信できます。
バージョン 2.0 の Address
クラスで、CountryField
フィールドが省略可能としてマークされるコード例を次に示します。バージョン 2.0 を必要とする新しいアプリケーションに対して、以前のアプリケーションがバージョン 1 を送信しても、データの不足は無視されます。
[Serializable]
public class Address
{
public string Street;
public string City;
[OptionalField]
public string CountryField;
}
<Serializable> _
Public Class Address
Public Street As String
Public City As String
<OptionalField> _
Public CountryField As String
End Class
シリアル化のコールバック
シリアル化のコールバックは、シリアル化および逆シリアル化プロセスに 4 つのポイントでフックを提供する機構です。
属性 | 関連付けられているメソッドが呼び出されるタイミング | 一般的な使用法 |
---|---|---|
逆シリアル化前 * |
省略可能なフィールドの既定値を初期化します。 |
|
逆シリアル化後 |
他のフィールドの内容に基づいて、省略可能なフィールドの値を固定します。 |
|
シリアル化前 |
シリアル化の準備を行います。たとえば、省略可能なデータ構造の作成などです。 |
|
シリアル化後 |
シリアル化イベントをログに記録します。 |
* このコールバックは、逆シリアル化コンストラクタ (存在する場合) の前に呼び出されます。
コールバックの使用
コールバックを使用するには、StreamingContext パラメータを受け取るメソッドに適切な属性を適用します。これらの属性では、1 つのクラスにつき 1 つのメソッドだけをマークできます。次に例を示します。
[OnDeserializing]
private void SetCountryRegionDefault(StreamingContext sc)
{
CountryField = "Japan";
}
[OnDeserializing]
private void SetCountryRegionDefault(StreamingContext sc)
{
CountryField = "Japan";
}
これらのメソッドの使用目的は、バージョン管理です。省略可能なフィールドのデータが不足していると、逆シリアル化の実行中、このフィールドが正しく初期化されないことがあります。この問題は、正しい値を割り当てるメソッドを作成してから、このメソッドに OnDeserializingAttribute または OnDeserializedAttribute 属性を適用することで解決できます。
型のコンテキストから見たメソッドのコード例を次に示します。以前のバージョンのアプリケーションが新しいバージョンのアプリケーションに Address
クラスのインスタンスを送信すると、CountryField
フィールドのデータが不足することになります。しかし、逆シリアル化後、このフィールドは既定値である "Japan" に設定されます。
[Serializable]
public class Address
{
public string Street;
public string City;
[OptionalField]
public string CountryField;
[OnDeserializing]
private void SetCountryRegionDefault (StreamingContext sc)
{
CountryField = "Japan";
}
}
<Serializable> _
Public Class Address
Public Street As String
Public City As String
<OptionalField> _
Public CountryField As String
<OnDeserializing> _
Private Sub SetCountryRegionDefault(StreamingContext sc)
CountryField = "Japan";
End Sub
End Class
VersionAdded プロパティ
OptionalFieldAttribute には VersionAdded プロパティがあります。.NET Framework バージョン 2.0 では、これは使用されません。ただし、将来のシリアル化エンジンとの型の互換性を維持するため、このプロパティを正しく設定しておくことが重要です。
このプロパティは、指定のフィールドが追加された型のバージョンを示します。次の例で示すように、このプロパティ値は型が変更されるつど、厳密に 1 ずつ増やす必要があります (開始値は 2)。
// Version 1.0
[Serializable]
public class Person
{
public string FullName;
}
// Version 2.0
[Serializable]
public class Person
{
public string FullName;
[OptionalField(VersionAdded = 2)]
public string NickName;
[OptionalField(VersionAdded = 2)]
public DateTime BirthDate;
}
// Version 3.0
[Serializable]
public class Person
{
public string FullName;
[OptionalField(VersionAdded=2)]
public string NickName;
[OptionalField(VersionAdded=2)]
public DateTime BirthDate;
[OptionalField(VersionAdded=3)]
public int Weight;
}
' Version 1.0
<Serializable> _
Public Class Person
Public FullName
End Class
' Version 2.0
<Serializable> _
Public Class Person
Public FullName As String
<OptionalField(VersionAdded := 2)> _
Public NickName As String
<OptionalField(VersionAdded := 2)> _
Public BirthDate As DateTime
End Class
' Version 3.0
<Serializable> _
Public Class Person
Public FullName As String
<OptionalField(VersionAdded := 2)> _
Public NickName As String
<OptionalField(VersionAdded := 2)> _
Public BirthDate As DateTime
<OptionalField(VersionAdded := 3)> _
Public Weight As Integer
End Class
ベスト プラクティス
バージョン管理が正しく行われるように、バージョン間で型を変更するときには次の規則に従ってください。
シリアル化したフィールドは削除しない。
NonSerializedAttribute 属性が以前のバージョンでフィールドに適用されていなかった場合は、新しいバージョンの該当フィールドにも適用しない。
シリアル化したフィールドの名前または型は変更しない。
新しいシリアル化フィールドを追加する場合は、OptionalFieldAttribute 属性を適用する。
以前のバージョンでシリアル化可能ではなかったフィールドから NonSerializedAttribute 属性を削除する場合は、OptionalFieldAttribute 属性を適用する。
すべての省略可能なフィールドに対して、既定値として 0 または null が許容される場合以外は、シリアル化コールバックを使用して意味のある既定値を設定する。
将来のシリアル化エンジンとの型の互換性を維持するには、次のガイドラインに従ってください。
常に OptionalFieldAttribute 属性の VersionAdded プロパティを正しく設定する。
バージョンの分岐は避ける。
参照
関連項目
SerializableAttribute
BinaryFormatter
SoapFormatter
VersionAdded
OptionalFieldAttribute
OnDeserializingAttribute
OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
StreamingContext
NonSerializedAttribute