Silverlight をインストールするには、ここをクリックします*
Japan変更|すべてのMicrosoft のサイト|サインイン
MSDN
|MSDN ライブラリ|デベロッパー センター|ダウンロード情報|開発ツール製品|コミュニティ|ご意見・ご要望|サイトマップ
MSDN Home  
MSDN Home > .NET Framework > .NET 開発者への道 〜 スキルアップキャンペーン 〜 > .NET Framework 2.0 コア機能解説 > 第 9 回 シリアル化

.NET Framework 2.0 コア機能解説

〜 第 9 回 シリアル化 〜

中 博俊
MSMVP for C#

■シリアル化 とは

皆さんはプログラムを作成するときにクラスなどを作成して、データを保持していたりすると思います。
ただこのメモリ上のデータは実体を保持している物もありますが、参照だけを保持しているなどという場合が多いと思います。
このようなメモリ上のデータはそのままファイルに保存することはできませんし、ネットワークを介して別のコンピュータに送ることもできません。完全に元に戻せるバイトの並び (シリアル) にすることを、シリアル化 (Serialize) / 逆シリアル化 (Deserialize) と言います。

このシリアル化をサポートする技術を .NET Framework では手厚く準備していますが、 .NET Framework2.0 になってより改善された 2 点について書きたいと思います。

■バージョン トレラントなシリアル化

トレラントとは寛容なという意味で、バージョンの変化に寛容なシリアル化という意味の機能です。簡単なクラスのシリアライズのサンプルは以下のようなものになります。

C#
[Serializable]
public class SerializedClass
{
	public string TextA;
}
〜〜
private void SaveButton_Click(object sender, EventArgs e)
{
	SerializedClass sc = new SerializedClass();
	sc.TextA = this.textBox1.Text;
	System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
	using( System.IO.FileStream fs = new System.IO.FileStream(@"c:\temp\test.bin", System.IO.FileMode.Create))
	{
		bf.Serialize(fs, sc);
	}
	this.textBox1.Text = "";
}
VB
<Serializable()> _
Public Class SerializedClass
	Public TextA As String
End Class
〜〜
Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveButton.Click
	Dim sc As New SerializedClass()
	sc.TextA = Me.textBox1.Text
	Dim bf = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
	Using fs As New System.IO.FileStream("c:\temp\test.bin", System.IO.FileMode.Create)
		bf.Serialize(fs, sc)
	End Using
	Me.textBox1.Text = ""
End Sub

このように Serializable 属性が付いているクラスを BinaryFormatter に渡すという簡易な方法で、シリアル化 / 逆シリアル化を行ってくれます。

SerializableAttribute クラス
http://msdn2.microsoft.com/ja-jp/library/system.serializableattribute(VS.80).aspx

BinaryFormatter クラス
http://msdn2.microsoft.com/ja-jp/library/system.runtime.serialization.formatters.binary.binaryformatter(VS.80).aspx

ただしシリアル化する情報が1つでも増えた場合にはどうなるでしょうか。 SerializedClass に 1 つ項目をそのまま増やしてみて、それを .NET Framework1.1 で実行してみましょう。

このように .NET Framework1.1 までのシリアル化 / 逆シリアル化は厳密に同じオブジェクトである必要がありました。
バージョンによるクラスの整合性に関して本来はプログラマが対応するコードを書かなければいけません。
ですが単純に項目が追加になっただけで、古いバージョンのデータを開いた場合には Null が設定されているだけでよいという場合が大多数でそのような場合には、 OptionalField 属性を利用します。

OptionalFieldAttribute クラス
http://msdn2.microsoft.com/ja-jp/library/system.runtime.serialization.optionalfieldattribute(vs.80).aspx

[Serializable]
public class SerializedClass
{
	public string TextA;
	[OptionalField]
	public string TextB;
}
<Serializable()> _
Public Class SerializedClass
	Public TextA As String
	<OptionalField()> _
	Public TextB As String
End Class

このように指定すると、逆シリアル化の際に OptionalField 属性の付いているフィールドは無視するようになります。

■XML シリアル化

先ほどのシリアル化はバイナリ形式でしたが、 XML 形式で保存すると人間がテキストとして見ることができるようになり非常に便利です。
.NET Frameworkは1.0 から XMLSerializer を搭載していましたが、クラス定義から XML の出力方法を決定するにあたりプログラムの実行中に決定していました。

XmlSerializer クラス
http://msdn2.microsoft.com/ja-jp/library/system.xml.serialization.xmlserializer(VS.80).aspx

これはプログラムを作成する際に決定できる事柄ですので、今回新たに Sgen というツールが提供されています。

XML シリアライザ ジェネレータ ツール (Sgen.exe)
http://msdn2.microsoft.com/ja-jp/library/bk3w6240(VS.80).aspx

まずスタートメニューの Visual Studio 2005 のコマンドラインから、コマンドプロンプトを立ち上げます。
sgen というコマンドに続いて、 /assembly: で対象になるアセンブリ (EXEかDLL) を指定します。 /out: で出力先のディレクトリを指定します。以下のような感じになります。

C:\Program Files\Microsoft Visual Studio 8\VC>sgen /assembly:"C:\temp\9-Serialization\BinarySerialize-CS\bin\Debug\BinarySerialize-CS.exe" /out:C:\temp\9-Serialization
Microsoft (R) Xml Serialization support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
シリアル化アセンブリの名前です: BinarySerialize-CS.XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
アセンブリ C:\temp\9-Serialization\BinarySerialize-CS\bin\Debug\BinarySerialize-CS.exe --> 'C:\temp\9-Serialization\BinarySerialize-CS.XmlSerializers.dll' に対してシリアル化アセンブリを生成しました。

この出力された DLL を参照することで、対象のクラス専用のシリアライザが利用できるようになります。
シリアル化するクラス専用の DLL を作成しておき、 DLL から自動的に DLL を作成するようにしておくと便利です。

C#
Microsoft.Xml.Serialization.GeneratedAssembly.SerializedClassSerializer scs = new Microsoft.Xml.Serialization.GeneratedAssembly.SerializedClassSerializer();
SerializedClass sc = new SerializedClass();
sc.TextA = this.textBox1.Text;
sc.TextB = this.textBox2.Text;
using( System.IO.FileStream fs = new System.IO.FileStream(@"c:\temp\test.xml", System.IO.FileMode.Create))
{
	scs.Serialize(fs, sc);
}
VB
Dim scs As New Microsoft.Xml.Serialization.GeneratedAssembly.SerializedClassSerializer()
Dim sc As New SerializedClass()
sc.TextA = Me.textBox1.Text
sc.TextB = Me.textBox2.Text
Using fs As New System.IO.FileStream("c:\temp\test.xml", System.IO.FileMode.Create)
	scs.Serialize(fs, sc)
End Using

■さいごに

シリアル化はバージョン管理も含めかなり仕様を確定させるのが難しい分野です。 .NET Framework 2.0 になり、いろいろな意味で柔軟になっているので、いろいろと試してみてください。

■参考資料

バージョン トレラントなシリアル化
http://msdn2.microsoft.com/ja-jp/library/ms229752(VS.80).aspx

Top of Page Top of Page


Microsoft