2010-10-22T03:10:15の更新内容

programming/netfx2/overview/serialization/index.wiki.txt

current previous
1,2727 1,1085
~
${smdncms:title,シリアライズ(System.Runtime.Serialization, System.Xml.Serialization)}
${smdncms:title,オブジェクトの永続化(System.Runtime.Serialization)}
+
${smdncms:keywords,シリアライズ,シリアル化,永続化,SOAP,XML,BinaryFormatter,SoapFormatter,XmlSerializer,ISerializable}
 
${smdncms:meta,toc-amazonlivelink-keyword,books-jp,.net framework}
${smdncms:meta,toc-amazonlivelink-keyword,books-jp,.net framework}
-
永続化とは実行中のプログラムにおけるオブジェクトの値を、ファイルなどの形にして永続的に保存しておくすることをいいます。 また、永続化したものを復元することを逆シリアル化と言います。 ここでは永続化とシリアル化は同じ意味ですが、ここではシリアル化という用語を用いて説明します。
-
#googleadunit
 

        

        
~
シリアライズ(serialize、永続化、シリアル化)とは実行中のアプリケーションにおけるオブジェクトの値を、バイナリ形式やXML形式などにすることを言います。 シリアライズすることによって、オブジェクトをファイルとして永続的に保存したり、ネットワーク経由で送信して別の場所で復元したりするといったことが出来るようになります。 シリアライズしたものをオブジェクトの形に復元することをデシリアライズ(deserialize、逆シリアル化)と言います。
*シリアル化の基本とXMLシリアル化
-
XMLシリアル化することによって、オブジェクトの値(ただしパブリックプロパティ・パブリックフィールドの値に限る)をXMLファイルに書き出すことができます。 さらに、逆シリアル化によってシリアル化によって作成した XMLファイルからオブジェクトの状態を復元する事ができます。 最も簡単なシリアル化の例を見てみましょう。
 

        

        
~
.NET FrameworkのSystem.Runtime.Serialization名前空間およびSystem.Xml.Serialization名前空間にはいくつかのシリアライザとその動作を制御するインターフェイス・属性が用意されています。 ここではシリアライズ・デシリアライズという用語を用いて、.NET Frameworkでのシリアライズについて解説します。
#code(vb){{
-
Imports System
-
Imports System.IO
-
Imports System.Xml
-
Imports System.Xml.Serialization
-
Imports System.Text
 

        

        
~
-関連するページ
Module Module1
+
--[[programming/netfx2/overview/attribute]]
 

        

        
~
注意1: この文章では&msdn(netfx,id,943242d1){XMLスキーマ定義ツール};については踏み込みません。 必要に応じて他のドキュメントを参照してください。
    Public Function Main(ByVal args() As String) As Integer
+
注意2: サンプルコードの一部で&msdn(netfx,id,bb385125){オブジェクト初期化子};や&msdn(netfx,id,dd293589){自動実装プロパティ};など言語のバージョンによってはサポートされていない機能を使っている箇所があります。 必要に応じて読み替え・書き換えを行ってください。
 

        

        
~
#googleadunit
        ' XMLシリアル化の対象となるインスタンスを作成
-
        Dim aibon As New ClassForSerialization("加護亜依", 15, "AB")
 

        

        
~
*シリアライズの基本
        ' XmlSerializer インスタンスを作成
~
**シリアライザを使わないシリアライズ
        Dim serializer As New XmlSerializer(aibon.GetType)
+
.NET Frameworkにはシリアライズを行うためのクラス群が用意さていますが、まずはシリアライザを使わずにシリアライズを行う場合について見てみます。 簡単な例として、BinaryWriter/BinaryReaderを使ってオブジェクトをファイルにシリアライズし、再びデシリアライズしてみます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+

          
+
class Account
+
{
+
  public int ID;
+
  public string Name;
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1}", ID, Name);
+
  }
+

          
+
  // シリアライズを行うメソッド
+
  public void Serialize(Stream stream)
+
  {
+
    BinaryWriter writer = new BinaryWriter(stream);
+

          
+
    writer.Write(ID);
+
    writer.Write(Name);
+
  }
+

          
+
  // デシリアライズを行うメソッド
+
  public void Deserialize(Stream stream)
+
  {
+
    BinaryReader reader = new BinaryReader(stream);
+

          
+
    ID = reader.ReadInt32();
+
    Name = reader.ReadString();
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // シリアライズするオブジェクトを作成
+
    Account alice = new Account();
+

          
+
    alice.ID = 2;
+
    alice.Name = "Alice";
+

          
+
    Console.WriteLine(alice);
+

          
+
    // オブジェクトをファイルalice.binとしてシリアライズする
+
    using (Stream stream = File.OpenWrite("alice.bin"))
+
    {
+
      alice.Serialize(stream);
+
    }
+

          
+
    // ファイルの内容を元にデシリアライズする
+
    Account deserialized = new Account();
+

          
+
    using (Stream stream = File.OpenRead("alice.bin"))
+
    {
+
      deserialized.Deserialize(stream);
+
    }
+

          
+
    Console.WriteLine(deserialized);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
 

        

        
~
Class Account
        ' XMLファイルを書き出すための StreamWriter インスタンスを作成
~
  Public ID As Integer
        Dim writer As New StreamWriter("E:\Serialization_00.xml", False, Encoding.UTF8)
+
  Public Name As String
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1}", ID, Name)
+
  End Function
+

          
+
  ' シリアライズを行うメソッド
+
  Public Sub Serialize(ByVal stream As Stream)
+
    Dim writer As New BinaryWriter(stream)
+

          
+
    writer.Write(ID)
+
    writer.Write(Name)
+
  End Sub
+

          
+
  ' デシリアライズを行うメソッド
+
  Public Sub Deserialize(ByVal stream As Stream)
+
    Dim reader As New BinaryReader(stream)
+

          
+
    ID = reader.ReadInt32()
+
    Name = reader.ReadString()
+
  End Sub
+
End Class
 

        

        
~
Class Sample
        ' XMLシリアル化
~
  Shared Sub Main()
        serializer.Serialize(writer, aibon)
+
    ' シリアライズするオブジェクトを作成
+
    Dim alice As New Account()
+

          
+
    alice.ID = 2
+
    alice.Name = "Alice"
+

          
+
    Console.WriteLine(alice)
+

          
+
    ' オブジェクトをファイルalice.binとしてシリアライズする
+
    Using stream As Stream = File.OpenWrite("alice.bin")
+
      alice.Serialize(stream)
+
    End Using
+

          
+
    ' ファイルの内容を元にデシリアライズする
+
    Dim deserialized As New Account()
+

          
+
    Using stream As Stream = File.OpenRead("alice.bin")
+
      deserialized.Deserialize(stream)
+
    End Using
 

        

        
~
    Console.WriteLine(deserialized)
        ' ファイルをクローズ
~
  End Sub
        writer.Close()
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt{{
        Return 0
+
2:Alice
+
2:Alice
+
}}
 

        

        
~
この例のように、シリアライズする際の形式さえ定義すれば.NET Frameworkのシリアライザを使わなくてもシリアライズ・デシリアライズを行うことは可能です。 しかしこの方法では、シリアライズを行いたいクラス毎にシリアライズの形式を定義して実装する必要がある、多数のメンバ変数を含むオブジェクトのシリアライズを実装するのは面倒であるという問題があります。
    End Function
 

        

        
~
**シリアライザを用いたシリアライズ
End Module
+
続いて、.NET Frameworkで用意されているシリアライザを使ってシリアライズする場合について見てみます。 次の例は、先の例と同じクラスを、BinaryFormatterを使ってファイルにシリアライズし、再びデシリアライズする例です。 (BinaryFormatterについては[[BinaryFormatter>#BinaryFormatter]]で解説します)
 

        

        
~
#tabpage(C#)
' シリアル化の対象となるクラス
~
#code(cs){{
<Serializable()> _
~
using System;
Public Class ClassForSerialization
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Binary;
 

        

        
~
[Serializable]
    ' シリアル化の対象となるメンバ
~
class Account
    Public Name As String
~
{
    Public Age As Integer
~
  public int ID;
    Public BloodType As String
+
  public string Name;
 

        

        
~
  public override string ToString()
    ' XMLシリアル化には既定のコンストラクタが必要
~
  {
    Public Sub New()
~
    return string.Format("{0}:{1}", ID, Name);
    End Sub
+
  }
+
}
 

        

        
~
class Sample
    ' コンストラクタ
~
{
    Public Sub New(ByVal Name As String, ByVal Age As Integer, ByVal BloodType As String)
+
  static void Main()
+
  {
+
    // シリアライズするオブジェクトを作成
+
    Account alice = new Account();
 

        

        
~
    alice.ID = 2;
        Me.Name = Name
~
    alice.Name = "Alice";
        Me.Age = Age
-
        Me.BloodType = BloodType
 

        

        
~
    Console.WriteLine(alice);
    End Sub
 

        

        
~
    // オブジェクトをファイルalice.binとしてシリアライズ
End Class
~
    using (Stream stream = File.OpenWrite("alice.bin"))
}}
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
 

        

        
~
      formatter.Serialize(stream, alice);
#code(xml,出力結果){{
~
    }
<?xml version="1.0" encoding="utf-8"?>
-
<ClassForSerialization xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
  <Name>加護亜依</Name>
-
  <Age>15</Age>
-
  <BloodType>AB</BloodType>
-
</ClassForSerialization>
-
}}
-

          
-
このファイルを見ればわかるように、XMLシリアル化によって ClassForSerializationクラスの各メンバの値がXMLファイルに出力されています。 では、ソースコードの動作についてみてみます。
 

        

        
~
    // ファイルの内容を元にデシリアライズする
まず、ClassForSerializationクラスを見ると、クラス宣言の一番始めに「<Serializable()>」という属性が付いています。 これはSerializableAttribute属性で、このクラスのインスタンスがシリアル化可能であることを示しています。 クラスの動作自体は問題ないと思います。 ただ、空のコンストラクタが宣言されているのは、シリアル化に際して既定のコンストラクタが必要なため意図的に宣言してあります(最初このことを知らずにいたので、何度やっても例外エラーが発生して困り果てていました)。
+
    Account deserialized = null;
 

        

        
~
    using (Stream stream = File.OpenRead("alice.bin"))
つづいて、Main()メソッドではコメントに書いてあるとおりのことをやっています。 15行目では、コンストラクタで指定した型をシリアル化するためのXMLSerializerクラスのインスタンスを作成しています。 型情報を取り出すためにインスタンスのGetType()メソッドを呼び出しています。 18行目で出力ファイルのコードページをUTF-8に設定しているのは、XMLファイルがUTF-8で出力されるからです。 続いてシリアル化本番の21行目でファイルストリームとシリアル化対象を渡してやります。 これでシリアル化が終わるので最後にファイルストリームをクローズしてやります。
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
 

        

        
~
      deserialized = (Account)formatter.Deserialize(stream);
このように、XMLシリアル化は簡単な手順で行うことができます。 続いて、シリアル化しただけではその能力の半分も使い切れていないので、逆シリアル化をしてみます。 逆シリアル化はその名の通りシリアル化の逆、つまりXMLファイルからクラスインスタンスの情報を復元します。
+
    }
 

        

        
+
    Console.WriteLine(deserialized);
+
  }
+
}
+
}}
+
#tabpage(VB)
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
~
Imports System.Runtime.Serialization
Imports System.Xml
~
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Xml.Serialization
-
Imports System.Text
-

          
-
Module Module1
-

          
-
    Public Function Main(ByVal args() As String) As Integer
-

          
-
        ' オブジェクト変数を宣言
-
        Dim aibon As ClassForSerialization
-

          
-
        ' XmlSerializer インスタンスを作成
-
        Dim serializer As New XmlSerializer(GetType(ClassForSerialization))
-

          
-
        ' XMLファイルを読み出すための StreamReader インスタンスを作成
-
        Dim reader As New StreamReader("E:\Serialization_00.xml")
-

          
-
        ' XMLシリアル化
-
        aibon = serializer.Deserialize(reader)
-

          
-
        ' ファイルをクローズ
-
        reader.Close()
-

          
-
        ' インスタンスのフィールド値を出力
-
        Console.WriteLine("名前: {0} ({1}歳, {2}型)", aibon.Name, aibon.Age, aibon.BloodType)
 

        

        
~
<Serializable> _
        Return 0
+
Class Account
+
  Public ID As Integer
+
  Public Name As String
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1}", ID, Name)
+
  End Function
+
End Class
 

        

        
~
Class Sample
    End Function
+
  Shared Sub Main()
+
    ' シリアライズするオブジェクトを作成
+
    Dim alice As New Account()
 

        

        
~
    alice.ID = 2
End Module
+
    alice.Name = "Alice"
 

        

        
~
    Console.WriteLine(alice)
' シリアル化の対象となるクラス
-
<Serializable()> _
-
Public Class ClassForSerialization
 

        

        
~
    ' オブジェクトをファイルalice.binとしてシリアライズ
    ' シリアル化の対象となるメンバ
~
    Using stream As Stream = File.OpenWrite("alice.bin")
    Public Name As String
~
      Dim formatter As New BinaryFormatter()
    Public Age As Integer
-
    Public BloodType As String
 

        

        
~
      formatter.Serialize(stream, alice)
    ' XMLシリアル化には既定のコンストラクタが必要
~
    End Using
    Public Sub New()
-
    End Sub
 

        

        
~
    ' ファイルの内容を元にデシリアライズする
    ' コンストラクタ
~
    Dim deserialized As Account = Nothing
    Public Sub New(ByVal Name As String, ByVal Age As Integer, ByVal BloodType As String)
 

        

        
~
    Using stream As Stream = File.OpenRead("alice.bin")
        Me.Name = Name
~
      Dim formatter As New BinaryFormatter()
        Me.Age = Age
-
        Me.BloodType = BloodType
 

        

        
~
      deserialized = CType(formatter.Deserialize(stream), Account)
    End Sub
+
    End Using
 

        

        
+
    Console.WriteLine(deserialized)
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt{{
#prompt(実行結果){{
~
2:Alice
名前: 加護亜依 (15歳, AB型)
~
2:Alice
Press any key to continue
+
}}
+

          
+
この例において、シリアライズされるクラスには&msdn(netfx,type,System.SerializableAttribute){Serializable};という属性が付与されている以外、シリアライズ・デシリアライズに関するコードが記述されていない点に注目してください。 .NET Frameworkのシリアライザでは&msdn(netfx,id,f7ykdhsy){リフレクション};によってメンバ変数を自動的に探してシリアライズするようになっています。 そのため、シリアライズを行いたいクラス毎にシリアライズの形式を決める必要も無く、クラスの構造によらず同じ手順でシリアライズすることが出来るようになっています。
+

          
+
**シリアライズの種類とシリアライザ
+
ここでは、いくつかのシリアライズの種類とシリアライザの使い方について簡単に見ていきます。 シリアライザの種類によっていくつかの制約があり、その違いを表にまとめると次のようになります。
+

          
+
|*シリアライザの種類と制約
+
||~[[BinaryFormatter>#BinaryFormatter]]&br;[[SoapFormatter>#SoapFormatter]]|~[[XmlSerializer>#XmlSerializer]]|h
+
|~SerializableAttribute|必須|付与されていなくてもよい|
+
|~シリアライズするクラス|パブリックでなくてもよい|バブリックでなければならない|
+
|~デフォルトコンストラクタ&br;(既定のコンストラクタ)|無くてもよい|必須|
+
|~シリアライズされるフィールド・プロパティ|すべてのフィールド・プロパティ|パブリックなフィールド・プロパティのみ|
+
|~型情報(アセンブリ名・型名)|シリアライズされる|シリアライズされない|
+

          
+
なお、BinaryFormatterおよびSoapFormatterは、シリアライズされるオブジェクトが自動実装プロパティ(&msdn(netfx,id,bb384054){C#};、&msdn(netfx,id,dd293589){VB};)を含んでいる場合でもバッキングフィールドの値を適切にシリアライズします。
+

          
+
***&aname(BinaryFormatter){BinaryFormatter};
+
&msdn(netfx,type,System.Runtime.Serialization.Formatters.Binary.BinaryFormatter){BinaryFormatter};(System.Runtime.Serialization.Formatters.Binary名前空間)は、その名のとおりバイナリ形式でのシリアライズ・デシリアライズを行うシリアライザです。 &msdn(netfx,method,System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize){Serializeメソッド};で指定されたオブジェクトを任意のStreamにシリアライズ、&msdn(netfx,method,System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize){Deserializeメソッド};でStreamからオブジェクトにデシリアライズすることが出来ます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Binary;
+

          
+
[Serializable]
+
class Account
+
{
+
  private int id;
+
  public string Name;
+

          
+
  public string ContactAddress
+
  {
+
    get; set;
+
  }
+

          
+
  public Account(int id)
+
  {
+
    this.id = id;
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} ({2})", id, Name, ContactAddress);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // シリアライズするオブジェクトを作成
+
    Account alice = new Account(2);
+

          
+
    alice.Name = "Alice";
+
    alice.ContactAddress = "alice@mail.example.net";
+

          
+
    Console.WriteLine(alice);
+

          
+
    // オブジェクトをファイルalice.binとしてシリアライズ
+
    using (Stream stream = File.OpenWrite("alice.bin"))
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    // ファイルの内容を元にデシリアライズする
+
    Account deserialized = null;
+

          
+
    using (Stream stream = File.OpenRead("alice.bin"))
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
+

          
+
      deserialized = (Account)formatter.Deserialize(stream);
+
    }
+

          
+
    Console.WriteLine(deserialized);
+
  }
+
}
 
}}
}}
~
#tabpage(VB)

          
~
#code(vb){{
実行結果は見ての通りで、見事保存されている値が読み込まれています。 ソースコードは先ほどとほとんど変わらないので説明するまでもありませんが、唯一説明すべきは15行目のXmlSerializerのインスタンスを作成するコードだと思います。 ここでも逆シリアル化するために必要な型情報を取得するのですが、取得できるインスタンスがないのでクラス型から直接GetTypeキーワードにより取り出しています。 また、実際に逆シリアル化されたインスタンスは、21行目のように、Deserialize()メソッドの戻り値として帰ってきます。
-

          
-
**シリアル化するために
-
シリアル化を行うためにはいくつか考慮すべき点があります。 MSDNにそれらをまとめた文章があるので一部引用させてもらい、ここに示します。
-

          
-
-シリアル化されたデータに含まれるのは、クラスの構造とデータだけです。型の識別子やアセンブリの情報は含まれません。
-
-シリアル化できるのは、パブリック プロパティとパブリック フィールドだけです。非パブリック データをシリアル化する必要がある場合は、XML シリアル化ではなく BinaryFormatter クラスを使用します。
-
-クラスを XmlSerializer でシリアル化するには、そのクラスに既定のコンストラクタがあることが必要です。
-
-メソッドはシリアル化できません。
-

          
-
シリアル化を行う際にはこの点を考慮しなければなりません。 実際に様々なスコープのプロパティ、フィールドをもったクラスを作成し、それをシリアル化した際に出力されるファイルを見てみることにします。
-

          
-
#code(vb,シリアル化されるメンバ、されないメンバ){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
~
Imports System.Runtime.Serialization
Imports System.Xml
~
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Xml.Serialization
-
Imports System.Text
-

          
-
Module Module1
-

          
-
    Public Function Main(ByVal args() As String) As Integer
-

          
-
        ' XMLシリアル化の対象となるインスタンスを作成
-
        Dim aibon As New ClassForSerialization("加護亜依", 15, "AB", New DateTime(1988, 2, 7), "奈良県")
-

          
-
        ' XmlSerializer インスタンスを作成
-
        Dim serializer As New XmlSerializer(aibon.GetType)
-

          
-
        ' XMLファイルを書き出すための StreamWriter インスタンスを作成
-
        Dim writer As New StreamWriter("E:\Serialization_01.xml", False, Encoding.UTF8)
-

          
-
        ' XMLシリアル化
-
        serializer.Serialize(writer, aibon)
-

          
-
        ' ファイルをクローズ
-
        writer.Close()
-

          
-
        Return 0
-

          
-
    End Function
-

          
-
End Module
-

          
-
' シリアル化の対象となるクラス
-
<Serializable()> _
-
Public Class ClassForSerialization
 

        

        
~
<Serializable> _
    ' パブリックフィールド
~
Class Account
    Public Name As String
~
  Private id As Integer
    Public Age As Integer
+
  Public Name As String
+

          
+
  Public Property ContactAddress As String
+

          
+
  Public Sub New(ByVal id As Integer)
+
    MyClass.id = id
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} ({2})", id, Name, ContactAddress)
+
  End Function
+
End Class
 

        

        
~
Class Sample
    ' プロテクティッドフィールド
~
  Shared Sub Main()
    Protected m_BloodType As String
+
    ' シリアライズするオブジェクトを作成
+
    Dim alice As New Account(2)
 

        

        
~
    alice.Name = "Alice"
    ' プライベートフィールド
~
    alice.ContactAddress = "alice@mail.example.net"
    Private m_BirthDate As DateTime
-
    Private m_BirthPlace As String
 

        

        
~
    Console.WriteLine(alice)
    ' パブリックプロパティ
-
    Public Property BirthDate() As DateTime
-
        Get
-
            Return m_BirthDate
-
        End Get
-
        Set(ByVal Value As DateTime)
-
            m_BirthDate = Value
-
        End Set
-
    End Property
 

        

        
~
    ' オブジェクトをファイルalice.binとしてシリアライズ
    ' プライベートプロパティ
~
    Using stream As Stream = File.OpenWrite("alice.bin")
    Private Property BirthPlace() As String
~
      Dim formatter As New BinaryFormatter()
        Get
-
            Return m_BirthPlace
-
        End Get
-
        Set(ByVal Value As String)
-
            m_birthplace = Value
-
        End Set
-
    End Property
 

        

        
~
      formatter.Serialize(stream, alice)
    ' XMLシリアル化には既定のコンストラクタが必要
~
    End Using
    Public Sub New()
-
    End Sub
 

        

        
~
    ' ファイルの内容を元にデシリアライズする
    ' コンストラクタ
~
    Dim deserialized As Account = Nothing
    Public Sub New(ByVal Name As String, ByVal Age As Integer, _
-
                    ByVal BloodType As String, ByVal BirthDate As DateTime, ByVal BirthPlace As String)
 

        

        
~
    Using stream As Stream = File.OpenRead("alice.bin")
        Me.Name = Name
~
      Dim formatter As New BinaryFormatter()
        Me.Age = Age
-
        Me.m_BloodType = BloodType
-
        Me.m_BirthDate = BirthDate
-
        Me.m_BirthPlace = BirthPlace
 

        

        
~
      deserialized = CType(formatter.Deserialize(stream), Account)
    End Sub
+
    End Using
 

        

        
+
    Console.WriteLine(deserialized)
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt(実行結果){{
#code(xml,出力結果){{
~
2:Alice (alice@mail.example.net)
<?xml version="1.0" encoding="utf-8"?>
~
2:Alice (alice@mail.example.net)
<ClassForSerialization xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
  <Name>加護亜依</Name>
-
  <Age>15</Age>
-
  <BirthDate>1988-02-07T00:00:00.0000000+09:00</BirthDate>
-
</ClassForSerialization>
 
}}
}}
 

        

        
~
以下は、上記のコードで生成されるファイルの内容をダンプしたものです。 このファイルを生成した実行ファイル名はser.exeです。
このように、パブリックなスコープを持つフィールド及びプロパティのみがシリアル化されます。 そのほかの値はシリアル化の対象から除外されます。 また、DateTime型の値の出力結果を見てみると、ToString()メソッドによって得られる文字列とは異なる値が出力されています。
-

          
-
**シリアル化の制御
-
XMLシリアル化ではパブリックなプロパティとフィールドがシリアル化の対象になりますが、必ずしもこれら全てをシリアル化の対象としたくない場合があります。 このような場合には、属性を用いることでシリアル化の制御を行うことができます。 まず、シリアル化の対象から除外する属性を使用した例を見てみます。
 

        

        
~
#code(,alice.binの内容){{
#code(vb,シリアル化対象から除外する){{
+
0000000  \0 001  \0  \0  \0 377 377 377 377 001  \0  \0  \0  \0  \0  \0
+
0000020  \0  \f 002  \0  \0  \0   :   s   e   r   ,       V   e   r   s
+
0000040   i   o   n   =   0   .   0   .   0   .   0   ,       C   u   l
+
0000060   t   u   r   e   =   n   e   u   t   r   a   l   ,       P   u
+
0000100   b   l   i   c   K   e   y   T   o   k   e   n   =   n   u   l
+
0000120   l 005 001  \0  \0  \0  \a   A   c   c   o   u   n   t 003  \0
+
0000140  \0  \0 002   i   d 004   N   a   m   e 037   <   C   o   n   t
+
0000160   a   c   t   A   d   d   r   e   s   s   >   k   _   _   B   a
+
0000200   c   k   i   n   g   F   i   e   l   d  \0 001 001  \b 002  \0
+
0000220  \0  \0 002  \0  \0  \0 006 003  \0  \0  \0 005   A   l   i   c
+
0000240   e 006 004  \0  \0  \0 026   a   l   i   c   e   @   m   a   i
+
0000260   l   .   e   x   a   m   p   l   e   .   n   e   t  \v
+
0000276
+
}}
+

          
+
***&aname(SoapFormatter){SoapFormatter};
+
&msdn(netfx,type,System.Runtime.Serialization.Formatters.Soap.SoapFormatter){SoapFormatter};(System.Runtime.Serialization.Formatters.Soap名前空間)は、SOAP形式でのシリアライズ・デシリアライズを行うシリアライザです。 [[SOAP>http://www.w3.org/TR/soap/]]は通信プロトコルの一種で、XMLをベースとしたリモートプロシージャコールを行うためのプロトコルです。 なお、SoapFormatterを使用する場合はアセンブリSystem.Runtime.Serialization.Formatters.Soap.dllを参照する必要があります。
+

          
+
BinaryFormatterと同様、&msdn(netfx,method,System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize){Serializeメソッド};でシリアライズ、&msdn(netfx,method,System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Deserialize){Deserializeメソッド};でデシリアライズすることが出来ます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Soap;
+

          
+
[Serializable]
+
class Account
+
{
+
  private int id;
+
  public string Name;
+

          
+
  public string ContactAddress
+
  {
+
    get; set;
+
  }
+

          
+
  public Account(int id)
+
  {
+
    this.id = id;
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} ({2})", id, Name, ContactAddress);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // シリアライズするオブジェクトを作成
+
    Account alice = new Account(2);
+

          
+
    alice.Name = "Alice";
+
    alice.ContactAddress = "alice@mail.example.net";
+

          
+
    Console.WriteLine(alice);
+

          
+
    // オブジェクトをファイルalice.soap.xmlとしてシリアライズ
+
    using (Stream stream = File.OpenWrite("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    // ファイルの内容を元にデシリアライズする
+
    Account deserialized = null;
+

          
+
    using (Stream stream = File.OpenRead("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      deserialized = (Account)formatter.Deserialize(stream);
+
    }
+

          
+
    Console.WriteLine(deserialized);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
~
Imports System.Runtime.Serialization
Imports System.Xml
~
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Xml.Serialization
-
Imports System.Text
-

          
-
Module Module1
-

          
-
    Public Function Main(ByVal args() As String) As Integer
-

          
-
        Dim aibon As New ClassForSerialization("加護亜依", 15, "AB", New DateTime(1988, 2, 7), "奈良県")
-
        Dim serializer As New XmlSerializer(aibon.GetType)
-
        Dim writer As New StreamWriter("E:\Serialization_02.xml", False, Encoding.UTF8)
-

          
-
        serializer.Serialize(writer, aibon)
-

          
-
        writer.Close()
 

        

        
~
<Serializable> _
        Return 0
+
Class Account
+
  Private id As Integer
+
  Public Name As String
+

          
+
  Public Property ContactAddress As String
+

          
+
  Public Sub New(ByVal id As Integer)
+
    MyClass.id = id
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} ({2})", id, Name, ContactAddress)
+
  End Function
+
End Class
 

        

        
~
Class Sample
    End Function
+
  Shared Sub Main()
+
    ' シリアライズするオブジェクトを作成
+
    Dim alice As New Account(2)
 

        

        
~
    alice.Name = "Alice"
End Module
+
    alice.ContactAddress = "alice@mail.example.net"
 

        

        
~
    Console.WriteLine(alice)
<Serializable()> _
-
Public Class ClassForSerialization
 

        

        
~
    ' オブジェクトをファイルalice.binとしてシリアライズ
    Public Name As String
~
    Using stream As Stream = File.OpenWrite("alice.bin")
    Public Age As Integer
~
      Dim formatter As New BinaryFormatter()
    <XmlIgnore()> Public BloodType As String
-
    <XmlIgnore()> Public BirthDate As DateTime
-
    Public BirthPlace As String
 

        

        
~
      formatter.Serialize(stream, alice)
    Public Sub New()
~
    End Using
    End Sub
 

        

        
~
    ' ファイルの内容を元にデシリアライズする
    Public Sub New(ByVal Name As String, ByVal Age As Integer, _
~
    Dim deserialized As Account = Nothing
                    ByVal BloodType As String, ByVal BirthDate As DateTime, ByVal BirthPlace As String)
 

        

        
~
    Using stream As Stream = File.OpenRead("alice.bin")
        Me.Name = Name
~
      Dim formatter As New BinaryFormatter()
        Me.Age = Age
-
        Me.BloodType = BloodType
-
        Me.BirthDate = BirthDate
-
        Me.BirthPlace = BirthPlace
 

        

        
~
      deserialized = CType(formatter.Deserialize(stream), Account)
    End Sub
+
    End Using
 

        

        
+
    Console.WriteLine(deserialized)
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt(実行結果){{
#code(xml,出力結果){{
~
2:Alice (alice@mail.example.net)
<?xml version="1.0" encoding="utf-8"?>
~
2:Alice (alice@mail.example.net)
<ClassForSerialization xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
  <Name>加護亜依</Name>
-
  <Age>15</Age>
-
  <BirthPlace>奈良県</BirthPlace>
-
</ClassForSerialization>
 
}}
}}
 

        

        
~
以下は、上記のコードで生成されるファイルの内容をダンプしたものです。 このファイルを生成した実行ファイル名はser.exeです。
シリアル化対象からメンバを除外する場合は、XmlIgnoreAttribute属性を用います。 ソースコードから想像できるように、出力結果には BloodType, BirthDateの値は出力されていないはずです。
 

        

        
~
#code(xml,alice.soap.xmlの内容){{
また、出力されるXMLファイルでの要素名を変更するにはXmlElementAttribute属性を用います。 この属性は要素名だけではなく、逆シリアライズ時における型の指定をすることもできます。 要素名を変更する場合の例が次のソースコードです。
+
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
+
<SOAP-ENV:Body>
+
<a1:Account id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/assem/ser%2C%20Version%3D0.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
+
<id>2</id>
+
<Name id="ref-3">Alice</Name>
+
<_x003C_ContactAddress_x003E_k__BackingField id="ref-4">alice@mail.example.net</_x003C_ContactAddress_x003E_k__BackingField>
+
</a1:Account>
+
</SOAP-ENV:Body>
+
</SOAP-ENV:Envelope>
+
}}
+

          
+
***&aname(XmlSerializer){XmlSerializer};
+
&msdn(netfx,type,System.Xml.Serialization.XmlSerializer){XmlSerializer};(System.Xml.Serialization名前空間)は、XML Schemaに準拠したXML形式でのシリアライズ・デシリアライズを行うシリアライザです。 BinaryFormatterやSoapFormatterとは異なり、XmlSerializerのコンストラクタでシリアライズ・デシリアライズするオブジェクトの型を指定する必要があります。
 

        

        
+
シリアライズ・デシリアライズは&msdn(netfx,method,System.Xml.Serialization.XmlSerializer.Serialize){Serializeメソッド};と&msdn(netfx,method,System.Xml.Serialization.XmlSerializer.Deserialize){Deserializeメソッド};で行いますが、BinaryFormatterやSoapFormatterとは異なり、StreamだけでなくXmlWriter/XmlReaderを使って行うことも出来ます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Xml;
+
using System.Xml.Serialization;
+

          
+
public class Account
+
{
+
  private int id;
+
  public string Name;
+

          
+
  public string ContactAddress
+
  {
+
    get; set;
+
  }
+

          
+
  // デフォルトコンストラクタ
+
  public Account() {}
+

          
+
  public Account(int id)
+
  {
+
    this.id = id;
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} ({2})", id, Name, ContactAddress);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // シリアライズするオブジェクトを作成
+
    Account alice = new Account(2);
+

          
+
    alice.Name = "Alice";
+
    alice.ContactAddress = "alice@mail.example.net";
+

          
+
    Console.WriteLine(alice);
+

          
+
    // オブジェクトをファイルalice.xmlとしてシリアライズ
+
    using (Stream stream = File.OpenWrite("alice.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(Account));
+

          
+
      serializer.Serialize(stream, alice);
+
    }
+

          
+
    // ファイルの内容を元にデシリアライズする
+
    Account deserialized = null;
+

          
+
    using (Stream stream = File.OpenRead("alice.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(Account));
+

          
+
      deserialized = (Account)serializer.Deserialize(stream);
+
    }
+

          
+
    Console.WriteLine(deserialized);
+
  }
+
}
+
}}
+
#tabpage(VB)
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
 
Imports System.Xml
Imports System.Xml
 
Imports System.Xml.Serialization
Imports System.Xml.Serialization
-
Imports System.Text
-

          
-
Module Module1
-

          
-
    Public Function Main(ByVal args() As String) As Integer
-

          
-
        Dim aibon As New ClassForSerialization("加護亜依", 15, "AB", New DateTime(1988, 2, 7), "奈良県")
-
        Dim serializer As New XmlSerializer(aibon.GetType)
-
        Dim writer As New StreamWriter("E:\Serialization_03.xml", False, Encoding.UTF8)
-

          
-
        serializer.Serialize(writer, aibon)
 

        

        
~
Public Class Account
        writer.Close()
~
  Private id As Integer

          
~
  Public Name As String
        Return 0
+

          
+
  Public Property ContactAddress As String
+

          
+
  ' デフォルトコンストラクタ
+
  Public Sub New()
+
  End Sub
+

          
+
  Public Sub New(ByVal id As Integer)
+
    MyClass.id = id
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} ({2})", id, Name, ContactAddress)
+
  End Function
+
End Class
 

        

        
~
Class Sample
    End Function
+
  Shared Sub Main()
+
    ' シリアライズするオブジェクトを作成
+
    Dim alice As New Account(2)
 

        

        
~
    alice.Name = "Alice"
End Module
+
    alice.ContactAddress = "alice@mail.example.net"
 

        

        
~
    Console.WriteLine(alice)
<Serializable()> _
-
Public Class ClassForSerialization
 

        

        
~
    ' オブジェクトをファイルalice.xmlとしてシリアライズ
    <XmlElement("氏名")> Public Name As String
~
    Using stream As Stream = File.OpenWrite("alice.xml")
    <XmlElement("年齢")> Public Age As Integer
~
      Dim serializer As New XmlSerializer(GetType(Account))
    <XmlElement("血液型")> Public BloodType As String
-
    <XmlElement("誕生日")> Public BirthDate As DateTime
-
    <XmlElement("出生地")> Public BirthPlace As String
 

        

        
~
      serializer.Serialize(stream, alice)
    Public Sub New()
~
    End Using
    End Sub
 

        

        
~
    ' ファイルの内容を元にデシリアライズする
    Public Sub New(ByVal Name As String, ByVal Age As Integer, _
~
    Dim deserialized As Account = Nothing
                    ByVal BloodType As String, ByVal BirthDate As DateTime, ByVal BirthPlace As String)
 

        

        
~
    Using stream As Stream = File.OpenRead("alice.xml")
        Me.Name = Name
~
      Dim serializer As New XmlSerializer(GetType(Account))
        Me.Age = Age
-
        Me.BloodType = BloodType
-
        Me.BirthDate = BirthDate
-
        Me.BirthPlace = BirthPlace
 

        

        
~
      deserialized = CType(serializer.Deserialize(stream), Account)
    End Sub
+
    End Using
 

        

        
+
    Console.WriteLine(deserialized)
+
  End Sub
 
End Class
End Class
-
}}
 

        

        
-
#code(xml,出力結果){{
-
<?xml version="1.0" encoding="utf-8"?>
-
<ClassForSerialization xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
  <氏名>加護亜依</氏名>
-
  <年齢>15</年齢>
-
  <血液型>AB</血液型>
-
  <誕生日>1988-02-07T00:00:00.0000000+09:00</誕生日>
-
  <出生地>奈良県</出生地>
-
</ClassForSerialization>
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt(実行結果){{
要素名を変更する必要性がある状況として、要素名とメンバ名を変えたい場合、例えば要素名に使用することは許可される名前でメンバ名では許可されない名前を使用する場合などが挙げられます(この例では要素名を日本語文字にしていますが、VB.NETではメンバ名に日本語文字を使用することは可能です)。
+
2:Alice (alice@mail.example.net)
+
0:Alice (alice@mail.example.net)
+
}}
 

        

        
~
実行結果において、フィールドidの値が復元されていない点に注目してください。 以下は、上記のコードで生成されるファイルの内容をダンプしたものです。
**配列のシリアル化
-
いままでは単一のクラスをシリアル化してきましたが、続いて複数のデータを持つような配列におけるシリアル化を行ってみます。 ただ、配列を直接シリアル化することはできないので、何らかの方法でクラスに内包する必要があります。 ここでは配列をパブリックフィールドとして保持するクラスを用いることで、間接的に配列をシリアル化しています。
 

        

        
+
#code(xml,alice.xmlの内容){{
+
<?xml version="1.0"?>
+
<Account xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
  <Name>Alice</Name>
+
  <ContactAddress>alice@mail.example.net</ContactAddress>
+
</Account>
+
}}
+

          
+
**配列・コレクションのシリアライズ
+
XmlSerializerやBinaryFormatterでは単純なオブジェクトだけでなく、配列やコレクションをシリアライズすることも出来ます。 ただし、独自のコレクションクラスをシリアライズ・デシリアライズする場合は、以下の制限に注意する必要があります。
+

          
+
+IEnumerableを実装している場合、デシリアライズの際に要素を追加するためのパブリックなメソッドAddも用意している必要がある
+
+ICollectionを実装している場合は、上記に加え、シリアライズの際に要素を参照するためのインデクサ(Itemプロパティ)と、要素の数を取得するためのCountプロパティも用意している必要がる
+
+IEnumerable、ICollectionが返す値の型と、Addメソッドの引数の型は互換性がある型である必要がある
+

          
+
また当然ながら、配列・コレクションに格納されている個々の要素もシリアライズ可能でなければなりません。 以下の例は、XmlSerializerで配列およびListをシリアライズする例です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Collections.Generic;
+
using System.IO;
+
using System.Xml;
+
using System.Xml.Serialization;
+

          
+
public class Account
+
{
+
  public int ID;
+
  public string Name;
+

          
+
  // デフォルトコンストラクタ
+
  public Account() {}
+

          
+
  public Account(int id, string name)
+
  {
+
    this.ID = id;
+
    this.Name = name;
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1}", ID, Name);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account[] arr = new Account[] {
+
      new Account(0, "Charlie"),
+
      new Account(1, "Eve"),
+
      new Account(2, "Alice"),
+
    };
+
    List<Account> list = new List<Account>(arr);
+

          
+
    // Account[]をシリアライズ
+
    using (Stream stream = File.OpenWrite("arr.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(arr.GetType());
+

          
+
      serializer.Serialize(stream, arr);
+
    }
+

          
+
    // List<Account>をシリアライズ
+
    using (Stream stream = File.OpenWrite("list.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(list.GetType());
+

          
+
      serializer.Serialize(stream, list);
+
    }
+

          
+
    // Account[]をデシリアライズ
+
    using (Stream stream = File.OpenRead("arr.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(Account[]));
+

          
+
      Account[] deserialized = (Account[])serializer.Deserialize(stream);
+

          
+
      Console.WriteLine("Account[]");
+

          
+
      foreach (Account e in deserialized)
+
      {
+
        Console.WriteLine(e);
+
      }
+
    }
+

          
+
    // List<Account>をデシリアライズ
+
    using (Stream stream = File.OpenRead("list.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(List<Account>));
+

          
+
      List<Account> deserialized = (List<Account>)serializer.Deserialize(stream);
+

          
+
      Console.WriteLine("List<Account>");
+

          
+
      foreach (Account e in deserialized)
+
      {
+
        Console.WriteLine(e);
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
+
Imports System.Collections.Generic
 
Imports System.IO
Imports System.IO
 
Imports System.Xml
Imports System.Xml
 
Imports System.Xml.Serialization
Imports System.Xml.Serialization
-
Imports System.Text
-

          
-
Module Module1
-

          
-
    Public Function Main(ByVal args() As String) As Integer
-

          
-
        ' インスタンスを作成
-
        Dim aibon As New Musume("加護亜依", New DateTime(1988, 2, 7))
-
        Dim konkon As New Musume("紺野あさ美", New DateTime(1987, 5, 7))
-
        Dim nacchi As New Musume("安部なつみ", New DateTime(1981, 8, 10))
-

          
-
        ' インスタンスから配列を作成する
-
        Dim members() As Musume = {aibon, konkon, nacchi}
-

          
-
        ' 配列を内包するクラスを作成
-
        Dim musume As New MorningMusume()
-
        musume.Members = members
-

          
-
        ' シリアル化
-
        Dim serializer As New XmlSerializer(musume.GetType())
-
        Dim writer As New StreamWriter("E:\Serialization_04.xml", False, Encoding.UTF8)
-

          
-
        serializer.Serialize(writer, musume)
-

          
-
        writer.Close()
-

          
-
        Return 0
-

          
-
    End Function
-

          
-
End Module
-

          
-
' MorningMusumeクラス
-
<Serializable()> _
-
Public Class MorningMusume
-

          
-
    <XmlArrayItem(GetType(Musume))> _
-
    Public Members As Musume()
-

          
-
    Public Sub New()
-
    End Sub
 

        

        
+
Public Class Account
+
  Public ID As Integer
+
  Public Name As String
+

          
+
  ' デフォルトコンストラクタ
+
  Public Sub New()
+
  End Sub
+

          
+
  Public Sub New(ByVal id As Integer, ByVal name As String)
+
    MyClass.ID = id
+
    MyClass.Name = name
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1}", ID, Name)
+
  End Function
 
End Class
End Class
 

        

        
~
Class Sample
' Musumeクラス
~
  Shared Sub Main()
Public Class Musume
~
    Dim arr() As Account = New Account() { _

          
~
      New Account(0, "Charlie"), _
    Public Name As String
~
      New Account(1, "Eve"), _
    Public Age As Integer
~
      New Account(2, "Alice") _
    Public BirthDate As DateTime
~
    }

          
~
    Dim list As New List(Of Account)(arr)
    Public Sub New()
~

          
    End Sub
~
    ' Account()をシリアライズ

          
~
    Using stream As Stream = File.OpenWrite("arr.xml")
    Public Sub New(ByVal Name As String, ByVal BirthDate As DateTime)
~
      Dim serializer As New XmlSerializer(arr.GetType())

          
~

          
        Me.Name = Name
~
      serializer.Serialize(stream, arr)
        Me.BirthDate = BirthDate
~
    End Using

          
~

          
        ' 年齢って誕生日から計算できますね・・・
~
    ' List(Of Account)をシリアライズ
        Me.Age = DateTime.Now.Year - BirthDate.Year
~
    Using stream As Stream = File.OpenWrite("list.xml")

          
~
      Dim serializer As New XmlSerializer(list.GetType())
        Dim birthDayInThisYear As New DateTime(DateTime.Now.Year, BirthDate.Month, BirthDate.Day)
~

          

          
~
      serializer.Serialize(stream, list)
        If birthDayInThisYear > DateTime.Now Then Me.Age -= 1
~
    End Using

          
~

          
    End Sub
~
    ' Account()をデシリアライズ

          
+
    Using stream As Stream = File.OpenRead("arr.xml")
+
      Dim serializer As New XmlSerializer(GetType(Account()))
+

          
+
      Dim deserialized() As Account = CType(serializer.Deserialize(stream), Account())
+

          
+
      Console.WriteLine("Account()")
+

          
+
      For Each e As Account In deserialized
+
        Console.WriteLine(e)
+
      Next
+
    End Using
+

          
+
    ' List(Of Account)をデシリアライズ
+
    Using stream As Stream = File.OpenRead("list.xml")
+
      Dim serializer As New XmlSerializer(GetType(List(Of Account)))
+

          
+
      Dim deserialized As List(Of Account) = CType(serializer.Deserialize(stream), List(Of Account))
+

          
+
      Console.WriteLine("List(Of Account)")
+

          
+
      For Each e As Account In deserialized
+
        Console.WriteLine(e)
+
      Next
+
    End Using
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt{{
#code(xml,出力結果){{
~
Account[]
<?xml version="1.0" encoding="utf-8"?>
~
0:Charlie
<MorningMusume xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
~
1:Eve
  <Members>
~
2:Alice
    <Musume>
~
List<Account>
      <Name>加護亜依</Name>
~
0:Charlie
      <Age>15</Age>
~
1:Eve
      <BirthDate>1988-02-07T00:00:00.0000000+09:00</BirthDate>
~
2:Alice
    </Musume>
~
}}
    <Musume>
~

          
      <Name>紺野あさ美</Name>
~
以下は、上記のコードで生成されるファイルの内容をダンプしたものです。
      <Age>15</Age>
~

          
      <BirthDate>1987-05-07T00:00:00.0000000+09:00</BirthDate>
~
#code(xml,arr.xml){{
    </Musume>
~
<?xml version="1.0"?>
    <Musume>
~
<ArrayOfAccount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Name>安部なつみ</Name>
~
  <Account>
      <Age>21</Age>
~
    <ID>0</ID>
      <BirthDate>1981-08-10T00:00:00.0000000+09:00</BirthDate>
~
    <Name>Charlie</Name>
    </Musume>
~
  </Account>
  </Members>
~
  <Account>
</MorningMusume>
+
    <ID>1</ID>
+
    <Name>Eve</Name>
+
  </Account>
+
  <Account>
+
    <ID>2</ID>
+
    <Name>Alice</Name>
+
  </Account>
+
</ArrayOfAccount>
+
}}
+

          
+
#code(xml,list.xml){{
+
<?xml version="1.0"?>
+
<ArrayOfAccount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
  <Account>
+
    <ID>0</ID>
+
    <Name>Charlie</Name>
+
  </Account>
+
  <Account>
+
    <ID>1</ID>
+
    <Name>Eve</Name>
+
  </Account>
+
  <Account>
+
    <ID>2</ID>
+
    <Name>Alice</Name>
+
  </Account>
+
</ArrayOfAccount>
+
}}
+

          
+
なお、SoapFormatterではジェネリックな型をシリアライズすることは出来ず、List<T>などをシリアライズしようとすると以下のようにSerializationExceptionがスローされます。 そのため、List<T>はToArrayメソッドなどを使って一旦配列などの形にしてからシリアライズする必要があります。
+

          
+
#prompt{{
+
ハンドルされていない例外: System.Runtime.Serialization.SerializationException: Soap シリアライザでは、ジェネリック タイプ System.Collections.Generic.List`1[Account] のシリアル化がサポートされていません。
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectWriter.Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize(Stream serializationStream, Object graph)
+
   場所 Sample.Main()
+
}}
+

          
+
**クラスの継承とシリアライズ
+
SerializableAttributeはInheritedフィールドがfalseとなっているため、SerializableAttributeを付与したクラスを継承する場合は派生クラスでもSerializableAttributeを付与しないとシリアライズ可能とはなりません。
+

          
+
以下の例は、SoapFormatterを使ってSerializableAttributeを付与した派生クラスをシリアライズ・デシリアライズする例です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Soap;
+

          
+
[Serializable]
+
abstract class AccountBase
+
{
+
  protected int ID;
+

          
+
  protected AccountBase(int id)
+
  {
+
    this.ID = id;
+
  }
+
}
+

          
+
[Serializable]
+
class Account : AccountBase
+
{
+
  public string Name;
+

          
+
  public Account(int id, string name)
+
    : base(id)
+
  {
+
    this.Name = name;
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1}", ID, Name);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account(2, "Alice");
+

          
+
    Console.WriteLine(alice);
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      Account deserialized = (Account)formatter.Deserialize(stream);
+

          
+
      Console.WriteLine(deserialized);
+
    }
+
  }
+
}
 
}}
}}
~
#tabpage(VB)

          
-
さらに、Object型の配列のように複数の型のデータが入る可能性のある場合は、属性でその入りうる型の情報を指定してやります。
-

          
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
~
Imports System.Runtime.Serialization
Imports System.Xml
~
Imports System.Runtime.Serialization.Formatters.Soap
Imports System.Xml.Serialization
-
Imports System.Text
 

        

        
~
<Serializable> _
Module Module1
+
MustInherit Class AccountBase
+
  Protected ID As Integer
+

          
+
  Protected Sub New(ByVal id As Integer)
+
    MyClass.ID = id
+
  End Sub
+
End Class
 

        

        
~
<Serializable> _
    Public Function Main(ByVal args() As String) As Integer
+
Class Account
+
  Inherits AccountBase
 

        

        
~
  Public Name As String
        Dim aibon As New Musume("加護亜依", New DateTime(1988, 2, 7), 4)
-
        Dim konkon As New Musume("紺野あさ美", New DateTime(1987, 5, 7), 5)
-
        Dim nacchi As New Musume("安部なつみ", New DateTime(1981, 8, 10), 1)
-
        Dim mikitty As New Girl("藤本美貴", New DateTime(1985, 2, 26))
-
        Dim ayaya As New Girl("松浦亜弥", New DateTime(1986, 6, 25))
 

        

        
~
  Public Sub New(ByVal id As Integer, ByVal name As String)
        Dim members() As Girl = {aibon, konkon, nacchi, mikitty, ayaya}
+
    MyBase.New(id)
 

        

        
~
    MyClass.Name = name
        Dim hello As New HelloProject()
~
  End Sub
        hello.Members = members
 

        

        
~
  Public Overrides Function ToString() As String
        Dim serializer As New XmlSerializer(hello.GetType())
~
    Return String.Format("{0}:{1}", ID, Name)
        Dim writer As New StreamWriter("E:\Serialization_05.xml", False, Encoding.UTF8)
+
  End Function
+
End Class
 

        

        
~
Class Sample
        serializer.Serialize(writer, hello)
+
  Shared Sub Main()
+
    Dim alice As New Account(2, "Alice")
 

        

        
~
    Console.WriteLine(alice)
        writer.Close()
 

        

        
~
    ' シリアライズ
        Return 0
+
    Using stream As Stream = File.OpenWrite("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
 

        

        
~
      formatter.Serialize(stream, alice)
    End Function
+
    End Using
 

        

        
~
    ' Account()をデシリアライズ
End Module
+
    Using stream As Stream = File.OpenRead("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
 

        

        
~
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
' HelloProjectクラス
-
<Serializable()> _
-
Public Class HelloProject
 

        

        
~
      Console.WriteLine(deserialized)
    <XmlArrayItem(GetType(Girl)), _
~
    End Using
     XmlArrayItem(GetType(Musume))> _
~
  End Sub
    Public Members As Girl()
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt{{
    Public Sub New()
~
2:Alice
    End Sub
+
2:Alice
+
}}
+

          
+
この例で、基底クラス・派生クラスどちらか一方でもSerializableAttributeが付与されていなければ、以下のようにSerializationExceptionがスローされます。
+

          
+
#prompt(AccountクラスにSerializableAttributeが付与されていない場合){{
+
ハンドルされていない例外: System.Runtime.Serialization.SerializationException:
+
アセンブリ 'ser, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' の型 'Account' はシリアル化可能として設定されていません。
+
   場所 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
+
   場所 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
+
   場所 System.Runtime.Serialization.Formatters.Soap.WriteObjectInfo.InitMemberInfo()
+
   場所 System.Runtime.Serialization.Formatters.Soap.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, SoapAttributeInfo attributeInfo, ObjectWriter objectWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, SoapAttributeInfo attributeInfo, ObjectWriter objectWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectWriter.Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize(Stream serializationStream, Object graph)
+
   場所 Sample.Main()
+
}}
+

          
+
#prompt(AccountBaseクラスにSerializableAttributeが付与されていない場合){{
+
ハンドルされていない例外: System.Runtime.Serialization.SerializationException:
+
アセンブリ 'ser, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' の型 'AccountBase' はシリアル化可能として設定されていません。
+
   場所 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
+
   場所 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
+
   場所 System.Runtime.Serialization.Formatters.Soap.WriteObjectInfo.InitMemberInfo()
+
   場所 System.Runtime.Serialization.Formatters.Soap.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, SoapAttributeInfo attributeInfo, ObjectWriter objectWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, SoapAttributeInfo attributeInfo, ObjectWriter objectWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectWriter.Serialize(Object graph, Header[] inHeaders, SoapWriter serWriter)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Serialize(Stream serializationStream, Object graph)
+
   場所 Sample.Main()
+
}}
+

          
+
XmlSerializerはSerializableAttributeをチェックしないので、基底クラス・派生クラスともにSerializableAttributeは不要です。
+

          
+
----
+

          
+
*BinaryFormatter, SoapFormatterの動作の制御
+
ここでは[[BinaryFormatter>#BinaryFormatter]]および[[SoapFormatter>#SoapFormatter]]を使ってシリアライズする場合の動作の制御について解説します。
+
**シリアライズ対象からの除外 (NonSerializedAttribute)
+
&msdn(netfx,type,System.NonSerializedAttribute){NonSerializedAttribute};を使用すると、フィールドをシリアライズ対象から除外することが出来ます。 BinaryFormatterおよびSoapFormatterではスコープに関わらずすべてのフィールドをシリアライズしようとしますが、シリアライズする必要の無いフィールドや実行時のみに使用されるフィールドなどは、この属性を使用することでシリアライズしないようにすることが出来ます。
+

          
+
以下の例では、Account.LastLoginフィールドにNonSerializedAttributeを付与しています。 デシリアライズ後にAccount.LastLoginフィールドの値が復元されていない点に注目してください。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Binary;
+

          
+
[Serializable]
+
class Account
+
{
+
  public int ID;
+
  public string Name;
+

          
+
  [NonSerialized]
+
  public DateTime LastLogin;
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account();
+

          
+
    alice.ID = 2;
+
    alice.Name = "Alice";
+
    alice.LastLogin = new DateTime(2010, 10, 20);
+

          
+
    Console.WriteLine(alice);
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("alice.bin"))
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("alice.bin"))
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
+

          
+
      Account deserialized = (Account)formatter.Deserialize(stream);
+

          
+
      Console.WriteLine(deserialized);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.Runtime.Serialization
+
Imports System.Runtime.Serialization.Formatters.Binary
 

        

        
+
<Serializable> _
+
Class Account
+
  Public ID As Integer
+
  Public Name As String
+

          
+
  <NonSerialized> _
+
  Public LastLogin As DateTime
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin)
+
  End Function
 
End Class
End Class
 

        

        
~
Class Sample
' Girlクラス
~
  Shared Sub Main()
Public Class Girl
+
    Dim alice As New Account()
 

        

        
~
    alice.ID = 2
    Public Name As String
~
    alice.Name = "Alice"
    Public Age As Integer
~
    alice.LastLogin = New DateTime(2010, 10, 20)
    Public BirthDate As DateTime
 

        

        
~
    Console.WriteLine(alice)
    Public Sub New()
-
    End Sub
 

        

        
~
    ' シリアライズ
    Public Sub New(ByVal Name As String, ByVal BirthDate As DateTime)
+
    Using stream As Stream = File.OpenWrite("alice.bin")
+
      Dim formatter As New BinaryFormatter()
 

        

        
~
      formatter.Serialize(stream, alice)
        Me.Name = Name
~
    End Using
        Me.BirthDate = BirthDate
 

        

        
~
    ' デシリアライズ
        Me.Age = DateTime.Now.Year - BirthDate.Year
+
    Using stream As Stream = File.OpenRead("alice.bin")
+
      Dim formatter As New BinaryFormatter()
 

        

        
~
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
        Dim birthDayInThisYear As New DateTime(DateTime.Now.Year, BirthDate.Month, BirthDate.Day)
 

        

        
~
      Console.WriteLine(deserialized)
        If birthDayInThisYear > DateTime.Now Then Me.Age -= 1
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt{{
    End Sub
+
2:Alice LastLogin=2010/10/20 0:00:00
+
2:Alice LastLogin=0001/01/01 0:00:00
+
}}
+

          
+
**追加されたフィールドの無視 (OptionalFieldAttribute)
+
&msdn(netfx,type,System.Runtime.Serialization.OptionalFieldAttribute){OptionalFieldAttribute};は新しいバージョンで追加されるフィールドに付与します。 例えば、あるバージョンでの型をシリアライズした後、型にフィールドを追加した新しいバージョンでデシリアライズしようとすると、古いバージョンのストリームには追加した新しいフィールドが含まれていないため例外がスローされます。 このような場合に例外をスローしないよう、追加したフィールドにはOptionalFieldAttributeを付与しておく必要があります。
+

          
+
例として、SoapFormatterを使って、二つのバージョンを跨いだシリアライズ・デシリアライズを行ってみます。 まずは、バージョン1のコードを使ってシリアライズを行います。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Soap;
+

          
+
// バージョン1のAccountクラス
+
[Serializable]
+
class Account
+
{
+
  public int ID;
+
  public string Name;
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1}", ID, Name);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account();
+

          
+
    alice.ID = 2;
+
    alice.Name = "Alice";
+

          
+
    Console.WriteLine(alice);
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.Runtime.Serialization
+
Imports System.Runtime.Serialization.Formatters.Soap
 

        

        
+
' バージョン1のAccountクラス
+
<Serializable> _
+
Class Account
+
  Public ID As Integer
+
  Public Name As String
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1}", ID, Name)
+
  End Function
 
End Class
End Class
 

        

        
~
Class Sample
' Musumeクラス
~
  Shared Sub Main()
Public Class Musume
~
    Dim alice As New Account()
    Inherits Girl
+

          
+
    alice.ID = 2
+
    alice.Name = "Alice"
+

          
+
    Console.WriteLine(alice)
+

          
+
    ' シリアライズ
+
    Using stream As Stream = File.OpenWrite("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
+

          
+
      formatter.Serialize(stream, alice)
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
バージョン1のAccountクラスには二つのフィールドIDとNameがあります。 このコードをビルドして実行ファイルser.exeを作成、実行します。 シリアライズされたalice.soap.xmlの内容は次のようになります。
    Public Generation As Integer
 

        

        
~
#code(xml,alice.soap.xmlの内容){{
    Public Sub New()
~
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    End Sub
+
<SOAP-ENV:Body>
+
<a1:Account id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/assem/ser%2C%20Version%3D0.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
+
<ID>2</ID>
+
<Name id="ref-3">Alice</Name>
+
</a1:Account>
+
</SOAP-ENV:Body>
+
</SOAP-ENV:Envelope>
+
}}
 

        

        
~
続いて、先ほどのコードを書き換え、バージョン2のコードを使ってデシリアライズを行います。
    Public Sub New(ByVal Name As String, ByVal BirthDate As DateTime, ByVal Generation As Integer)
 

        

        
~
#tabpage(C#)
        MyBase.New(Name, BirthDate)
~
#code(cs){{
        Me.Generation = Generation
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Soap;
+

          
+
// バージョン2のAccountクラス
+
[Serializable]
+
class Account
+
{
+
  public int ID;
+
  public string Name;
+

          
+
  // バージョン2で新しく追加したフィールド
+
  [OptionalField]
+
  public string ContactAddress;
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} ContactAddress={2}", ID, Name, ContactAddress);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      Account deserialized = (Account)formatter.Deserialize(stream);
+

          
+
      Console.WriteLine(deserialized);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.Runtime.Serialization
+
Imports System.Runtime.Serialization.Formatters.Soap
 

        

        
~
' バージョン2のAccountクラス
    End Sub
+
<Serializable> _
+
Class Account
+
  Public ID As Integer
+
  Public Name As String
+

          
+
  ' バージョン2で新しく追加したフィールド
+
  <OptionalField> _
+
  Public ContactAddress As String
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} ContactAddress={2}", ID, Name, ContactAddress)
+
  End Function
+
End Class
 

        

        
+
Class Sample
+
  Shared Sub Main()
+
    ' デシリアライズ
+
    Using stream As Stream = File.OpenRead("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
+

          
+
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
+

          
+
      Console.WriteLine(deserialized)
+
    End Using
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
バージョン2のAccountクラスには、バージョン1から存在するフィールドID・Nameと、バージョン2で新しく追加したフィールドContactAddressがあります。 このコードをビルドして実行ファイルser.exeを作成、実行すると、特に問題なくデシリアライズ出来ます。
#code(xml,出力結果){{
-
<?xml version="1.0" encoding="utf-8"?>
-
<MorningMusume xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-
  <Members>
-
    <Musume>
-
      <Name>加護亜依</Name>
-
      <Age>15</Age>
-
      <BirthDate>1988-02-07T00:00:00.0000000+09:00</BirthDate>
-
      <Generation>4</Generation>
-
    </Musume>
-
    <Musume>
-
      <Name>紺野あさ美</Name>
-
      <Age>15</Age>
-
      <BirthDate>1987-05-07T00:00:00.0000000+09:00</BirthDate>
-
      <Generation>5</Generation>
-
    </Musume>
-
    <Musume>
-
      <Name>安部なつみ</Name>
-
      <Age>21</Age>
-
      <BirthDate>1981-08-10T00:00:00.0000000+09:00</BirthDate>
-
      <Generation>1</Generation>
-
    </Musume>
-
    <Girl>
-
      <Name>藤本美貴</Name>
-
      <Age>18</Age>
-
      <BirthDate>1985-02-26T00:00:00.0000000+09:00</BirthDate>
-
    </Girl>
-
    <Girl>
-
      <Name>松浦亜弥</Name>
-
      <Age>16</Age>
-
      <BirthDate>1986-06-25T00:00:00.0000000+09:00</BirthDate>
-
    </Girl>
-
  </Members>
-
</MorningMusume>
-
}}
 

        

        
~
#prompt{{
これによって出力されたファイルを逆シリアル化するには次のコードの様に行います(クラスの設計は全く変えません)。
+
2:Alice ContactAddress=
+
}}
 

        

        
+
しかし、これをOptionalFieldAttributeを付与していない状態で実行すると、以下のようにSerializationExceptionがスローされます。
+

          
+
#prompt{{
+
ハンドルされていない例外: System.Runtime.Serialization.SerializationException:
+
メンバの数が間違っています。オブジェクト Account には 3 メンバ含まれていますが、逆シリアル化されたメンバの数は 2 です。
+
   場所 System.Runtime.Serialization.Formatters.Soap.ReadObjectInfo.PopulateObjectMembers()
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectReader.ParseObjectEnd(ParseRecord pr)
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectReader.Parse(ParseRecord pr)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapHandler.EndElement(String prefix, String name, String urn)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapParser.ParseXml()
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapParser.Run()
+
   場所 System.Runtime.Serialization.Formatters.Soap.ObjectReader.Deserialize(HeaderHandler handler, ISerParser serParser)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Deserialize(Stream serializationStream, HeaderHandler handler)
+
   場所 System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Deserialize(Stream serializationStream)
+
   場所 Sample.Main()
+
}}
+

          
+
なお、BinaryFormatterを使った場合はOptionalFieldAttributeが付与されていなくても特に例外はスローされないようですが、念のため付与しておいたほうがよいと思われます。
+

          
+
**シリアライズ前後のコールバック (OnSerializingAttribute, OnSerializedAttribute, OnDeserializingAttribute, OnDeserializedAttribute)
+
シリアライズ・デシリアライズの前後で値の検証やデフォルト値の設定などの追加の処理を行いたい場合は、次の属性を使用することでシリアライザにコールバックさせることが出来ます。 これらの属性はフィールドではなくコールバック用のメソッドに付与します。
+

          
+
|*コールバックを指定するための属性
+
|~属性|~機能|h
+
|&msdn(netfx,type,System.Runtime.Serialization.OnSerializingAttribute){OnSerializingAttribute};|シリアライズ前にコールバックするメソッドを指定する|
+
|&msdn(netfx,type,System.Runtime.Serialization.OnSerializedAttribute){OnSerializedAttribute};|シリアライズ後にコールバックするメソッドを指定する|
+
|&msdn(netfx,type,System.Runtime.Serialization.OnDeserializingAttribute){OnDeserializingAttribute};|デシリアライズ前にコールバックするメソッドを指定する|
+
|&msdn(netfx,type,System.Runtime.Serialization.OnDeserializedAttribute){OnDeserializedAttribute};|デシリアライズ後にコールバックするメソッドを指定する|
+

          
+
なお、これらの属性を付与するメソッドは、&msdn(netfx,type,System.Runtime.Serialization.StreamingContext){StreamingContext};を引数にとる必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Binary;
+

          
+
[Serializable]
+
class Account
+
{
+
  public int ID;
+
  public string Name;
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1}", ID, Name);
+
  }
+

          
+
  [OnSerializing]
+
  private void OnSerializing(StreamingContext context)
+
  {
+
    Console.WriteLine("OnSerializing");
+
  }
+

          
+
  [OnSerialized]
+
  private void OnSerialized(StreamingContext context)
+
  {
+
    Console.WriteLine("OnSerialized");
+
  }
+

          
+
  [OnDeserializing]
+
  private void OnDeserializing(StreamingContext context)
+
  {
+
    Console.WriteLine("OnDeserializing");
+
  }
+

          
+
  [OnDeserialized]
+
  private void OnDeserialized(StreamingContext context)
+
  {
+
    Console.WriteLine("OnDeserialized");
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account();
+

          
+
    alice.ID = 2;
+
    alice.Name = "Alice";
+

          
+
    Console.WriteLine(alice);
+

          
+
    using (Stream stream = File.OpenWrite("alice.bin"))
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
+

          
+
      Console.WriteLine("Serialize");
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    using (Stream stream = File.OpenRead("alice.bin"))
+
    {
+
      BinaryFormatter formatter = new BinaryFormatter();
+

          
+
      Console.WriteLine("Deserialize");
+

          
+
      Account deserialized = (Account)formatter.Deserialize(stream);
+

          
+
      Console.WriteLine(deserialized);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
 
#code(vb){{
#code(vb){{
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
~
Imports System.Runtime.Serialization
Imports System.Xml
~
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Xml.Serialization
-
Imports System.Text
-

          
-
Module Module1
-

          
-
    Public Function Main(ByVal args() As String) As Integer
 

        

        
~
<Serializable> _
        Dim hello As New HelloProject()
~
Class Account
        Dim serializer As New XmlSerializer(hello.GetType())
~
  Public ID As Integer
        Dim reader As New StreamReader("E:\Serialization_05.xml")
+
  Public Name As String
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1}", ID, Name)
+
  End Function
+

          
+
  <OnSerializing> _
+
  Private Sub OnSerializing(ByVal context As StreamingContext)
+
    Console.WriteLine("OnSerializing")
+
  End Sub
+

          
+
  <OnSerialized> _
+
  Private Sub OnSerialized(ByVal context As StreamingContext)
+
    Console.WriteLine("OnSerialized")
+
  End Sub
+

          
+
  <OnDeserializing> _
+
  Private Sub OnDeserializing(ByVal context As StreamingContext)
+
    Console.WriteLine("OnDeserializing")
+
  End Sub
+

          
+
  <OnDeserialized> _
+
  Private Sub OnDeserialized(ByVal context As StreamingContext)
+
    Console.WriteLine("OnDeserialized")
+
  End Sub
+
End Class
 

        

        
~
Class Sample
        hello = serializer.Deserialize(reader)
+
  Shared Sub Main()
+
    Dim alice As New Account()
 

        

        
~
    alice.ID = 2
        reader.Close()
+
    alice.Name = "Alice"
 

        

        
~
    Console.WriteLine(alice)
        Dim girl As Girl
 

        

        
~
    Using stream As Stream = File.OpenWrite("alice.bin")
        For Each girl In hello.Members
+
      Dim formatter As New BinaryFormatter()
 

        

        
~
      Console.WriteLine("Serialize")
            Console.Write("名前: {0} ({1}歳, 誕生日{2}) ", girl.Name, girl.Age, girl.BirthDate.ToLongDateString)
 

        

        
~
      formatter.Serialize(stream, alice)
            If TypeOf girl Is Musume Then
+
    End Using
 

        

        
~
    Using stream As Stream = File.OpenRead("alice.bin")
                Console.WriteLine("第" + CType(girl, Musume).Generation.ToString() + "期メンバー")
+
      Dim formatter As New BinaryFormatter()
 

        

        
~
      Console.WriteLine("Deserialize")
            Else
 

        

        
~
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
                Console.Write(vbNewLine)
 

        

        
~
      Console.WriteLine(deserialized)
            End If
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt{{
        Next
+
2:Alice
+
Serialize
+
OnSerializing
+
OnSerialized
+
Deserialize
+
OnDeserializing
+
OnDeserialized
+
2:Alice
+
}}
+

          
+
**&aname(ISerializable){シリアライズ動作の制御 (ISerializable)};
+
&msdn(netfx,type,System.Runtime.Serialization.ISerializable){ISerializableインターフェイス};を使うことで、ここまでに解説してきた属性を用いるよるも柔軟にシリアライズ・デシリアライズ時の動作を制御することが出来ます。 例えば、シリアライズする値とその名前を指定したり、シリアライズ・デシリアライズの前後でデフォルト値の設定や値のチェックの処理を追加することも出来ます。
+

          
+
ISerializableを実装する場合は、シリアライズを行うためのメソッド&msdn(netfx,method,System.Runtime.Serialization.ISerializable.GetObjectData){ISerializable.GetObjectData};とデシリアライズを行うためのコンストラクタを用意する必要があります。 これらはどちらもパブリックである必要はありません。
+

          
+
このメソッドとコンストラクタでは、引数の一つにシリアライズ・デシリアライズする値を格納するための&msdn(netfx,type,System.Runtime.Serialization.SerializationInfo){SerializationInfo};を取ります。 シリアライズする値を追加するには&msdn(netfx,method,System.Runtime.Serialization.SerializationInfo.AddValue){AddValueメソッド};、デシリアライズされた値を取得するには&msdn(netfx,method,System.Runtime.Serialization.SerializationInfo.GetString){GetStringメソッド};や&msdn(netfx,method,System.Runtime.Serialization.SerializationInfo.GetValue){GetValueメソッド};などを使います。 この時、値とその名前を指定出来ますが、名前にはフィールド名ではなく任意の名前を代わりに指定することも出来ます。
+

          
+
次の例は、ISerializableを使ってシリアライズ・デシリアライズを行う例です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Soap;
+

          
+
[Serializable]
+
class Account : ISerializable
+
{
+
  public int ID;
+
  public string Name;
+
  public Uri[] ContactAddresses;
+
  public DateTime LastLogin;
+

          
+
  public Account(int id, string name)
+
  {
+
    this.ID = id;
+
    this.Name = name;
+
  }
+

          
+
  // デシリアライズの際に呼び出されるコンストラクタ
+
  private Account(SerializationInfo info, StreamingContext context)
+
  {
+
    this.ID = info.GetInt32("ID");
+
    this.Name = info.GetString("名前");
+
    this.ContactAddresses = (Uri[])info.GetValue("連絡先", typeof(Uri[]));
+

          
+
    this.LastLogin = new DateTime(2000, 1, 1);
+
  }
+

          
+
  // ISerializable.GetObjectDataの明示的な実装
+
  void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+
  {
+
    info.AddValue("ID", ID);
+
    info.AddValue("名前", Name);
+
    info.AddValue("連絡先", ContactAddresses, typeof(Uri[]));
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} LastLogin={2} ContactAddresses={3}",
+
                         ID,
+
                         Name,
+
                         LastLogin,
+
                         string.Join(", ", Array.ConvertAll<Uri, string>(ContactAddresses, Convert.ToString)));
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account(2, "Alice");
+

          
+
    alice.ContactAddresses = new Uri[] {
+
      new Uri("mailto:alice@mail.example.net"),
+
      new Uri("http://example.com/~alice/")
+
    };
+
    alice.LastLogin = new DateTime(2010, 10, 20);
+

          
+
    Console.WriteLine(alice);
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      Account deserialized = (Account)formatter.Deserialize(stream);
+

          
+
      Console.WriteLine(deserialized);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.Runtime.Serialization
+
Imports System.Runtime.Serialization.Formatters.Soap
 

        

        
~
<Serializable> _
        Return 0
+
Class Account
+
  Implements ISerializable
+

          
+
  Public ID As Integer
+
  Public Name As String
+
  Public ContactAddresses() As Uri
+
  Public LastLogin As DateTime
+

          
+
  Public Sub New(ByVal id As Integer, ByVal name As String)
+
    MyClass.ID = id
+
    MyClass.Name = name
+
  End SUb
+

          
+
  ' デシリアライズの際に呼び出されるコンストラクタ
+
  Private Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
+
    MyClass.ID = info.GetInt32("ID")
+
    MyClass.Name = info.GetString("名前")
+
    MyClass.ContactAddresses = CType(info.GetValue("連絡先", GetType(Uri())), Uri())
+

          
+
    MyClass.LastLogin = new DateTime(2000, 1, 1)
+
  End SUb
+

          
+
  ' ISerializable.GetObjectDataの実装
+
  Private Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData
+
    info.AddValue("ID", ID)
+
    info.AddValue("名前", Name)
+
    info.AddValue("連絡先", ContactAddresses, GetType(Uri()))
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} LastLogin={2} ContactAddresses={3}", _
+
                         ID, _
+
                         Name, _
+
                         LastLogin, _
+
                         String.Join(", ", Array.ConvertAll(ContactAddresses, AddressOf Convert.ToString)))
+
  End Function
+
End Class
 

        

        
~
Class Sample
    End Function
+
  Shared Sub Main()
+
    Dim alice As New Account(2, "Alice")
+

          
+
    alice.ContactAddresses = New Uri() { _
+
      New Uri("mailto:alice@mail.example.net"), _
+
      New Uri("http://example.com/~alice/") _
+
    }
+
    alice.LastLogin = New DateTime(2010, 10, 20)
+

          
+
    Console.WriteLine(alice)
+

          
+
    ' シリアライズ
+
    Using stream As Stream = File.OpenWrite("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
+

          
+
      formatter.Serialize(stream, alice)
+
    End Using
+

          
+
    ' デシリアライズ
+
    Using stream As Stream = File.OpenRead("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
+

          
+
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
+

          
+
      Console.WriteLine(deserialized)
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#prompt{{
End Module
+
2:Alice LastLogin=2010/10/20 0:00:00 ContactAddresses=mailto:alice@mail.example.net, http://example.com/~alice/
+
2:Alice LastLogin=2000/01/01 0:00:00 ContactAddresses=mailto:alice@mail.example.net, http://example.com/~alice/
 
}}
}}
 

        

        
~
結果を見てのとおり、適切にデシリアライズされていることが分かると思います。 なお、SerializationInfo.AddValueで指定した値の名前は、値を格納するXML要素の名前としても使われます。 以下はシリアライズされたalice.soap.xmlの内容です。 Account.LastLoginフィールドの値はSerializationInfoに追加していないため、シリアライズされた内容には含まれていない点にも注目してください。
#prompt(実行結果){{
~

          
名前: 加護亜依 (15歳, 誕生日1988年2月7日) 第4期メンバー
~
#code(xml,alice.soap.xmlの内容){{
名前: 紺野あさ美 (15歳, 誕生日1987年5月7日) 第5期メンバー
~
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
名前: 安倍なつみ (21歳, 誕生日1981年8月10日) 第1期メンバー
~
<SOAP-ENV:Body>
名前: 藤本美貴 (18歳, 誕生日1985年2月26日)
~
<a1:Account id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/assem/ser%2C%20Version%3D0.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
名前: 松浦亜弥 (16歳, 誕生日1986年6月25日)
~
<ID>2</ID>
Press any key to continue
+
<名前 id="ref-4">Alice</名前>
+
<連絡先 href="#ref-5"/>
+
</a1:Account>
+
<SOAP-ENC:Array id="ref-5" SOAP-ENC:arrayType="a2:Uri[2]" xmlns:a2="http://schemas.microsoft.com/clr/nsassem/System/System%2C%20Version%3D2.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db77a5c561934e089">
+
<item href="#ref-6"/>
+
<item href="#ref-7"/>
+
</SOAP-ENC:Array>
+
<a2:Uri id="ref-6" xmlns:a2="http://schemas.microsoft.com/clr/nsassem/System/System%2C%20Version%3D2.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db77a5c561934e089">
+
<AbsoluteUri id="ref-8">mailto:alice@mail.example.net</AbsoluteUri>
+
</a2:Uri>
+
<a2:Uri id="ref-7" xmlns:a2="http://schemas.microsoft.com/clr/nsassem/System/System%2C%20Version%3D2.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db77a5c561934e089">
+
<AbsoluteUri id="ref-9">http://example.com/~alice/</AbsoluteUri>
+
</a2:Uri>
+
</SOAP-ENV:Body>
+
</SOAP-ENV:Envelope>
 
}}
}}
 

        

        
~
ISerializableインターフェイスを実装するクラスを継承可能にするには、コンストラクタとメソッドを派生クラスに公開し、オーバーライドできるようにしておく必要があります。 派生クラスでは、SerializationInfoを基底クラスに引き渡すことで基底クラスのフィールドをシリアライズ・デシリアライズさせるようにします。 以下の例では、基底クラスでISerializableを実装し、その派生クラスをシリアライズしています。
*SOAPシリアル化
-
ここまではXML形式でのシリアル化を行ってきましたが、シリアル化の形式はXML以外にも存在します。 ここではSOAPプロトコル形式でのシリアル化を行ってみます。
 

        

        
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Soap;
+

          
+
[Serializable]
+
class AccountBase : ISerializable
+
{
+
  protected int ID;
+
  protected string Name;
+

          
+
  protected AccountBase(int id, string name)
+
  {
+
    this.ID = id;
+
    this.Name = name;
+
  }
+

          
+
  // デシリアライズの際に呼び出されるコンストラクタ
+
  protected AccountBase(SerializationInfo info, StreamingContext context)
+
  {
+
    this.ID = info.GetInt32("ID");
+
    this.Name = info.GetString("名前");
+
  }
+

          
+
  // ISerializable.GetObjectDataの明示的な実装
+
  void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+
  {
+
    // オーバーライド可能なメソッドを呼び出す
+
    GetObjectData(info, context);
+
  }
+

          
+
  // シリアライズする値を追加する
+
  protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+
  {
+
    info.AddValue("ID", ID);
+
    info.AddValue("名前", Name);
+
  }
+
}
+

          
+
[Serializable]
+
class Account : AccountBase
+
{
+
  public Uri[] ContactAddresses;
+

          
+
  public Account(int id, string name)
+
    : base(id, name)
+
  {
+
  }
+

          
+
  // デシリアライズの際に呼び出されるコンストラクタ
+
  protected Account(SerializationInfo info, StreamingContext context)
+
    : base(info, context)
+
  {
+
    this.ContactAddresses = (Uri[])info.GetValue("連絡先", typeof(Uri[]));
+
  }
+

          
+
  // GetObjectDataをオーバーライド
+
  protected override void GetObjectData(SerializationInfo info, StreamingContext context)
+
  {
+
    // 基底クラスのシリアライズ情報を取得
+
    base.GetObjectData(info, context);
+

          
+
    info.AddValue("連絡先", ContactAddresses, typeof(Uri[]));
+
  }
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} ContactAddresses={2}",
+
                         ID,
+
                         Name,
+
                         string.Join(", ", Array.ConvertAll<Uri, string>(ContactAddresses, Convert.ToString)));
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account(2, "Alice");
+

          
+
    alice.ContactAddresses = new Uri[] {
+
      new Uri("mailto:alice@mail.example.net"),
+
      new Uri("http://example.com/~alice/")
+
    };
+

          
+
    Console.WriteLine(alice);
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      formatter.Serialize(stream, alice);
+
    }
+

          
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("alice.soap.xml"))
+
    {
+
      SoapFormatter formatter = new SoapFormatter();
+

          
+
      Account deserialized = (Account)formatter.Deserialize(stream);
+

          
+
      Console.WriteLine(deserialized);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
 
#code(vb){{
#code(vb){{
-
Option Strict On
-

          
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
 
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization
 
Imports System.Runtime.Serialization.Formatters.Soap
Imports System.Runtime.Serialization.Formatters.Soap
 

        

        
~
<Serializable> _
Module MainModule
~
Class AccountBase

          
~
  Implements ISerializable
    Sub Main()
+

          
+
  Protected ID As Integer
+
  Protected Name As String
+

          
+
  Protected Sub New(ByVal id As Integer, ByVal name As String)
+
    MyClass.ID = id
+
    MyClass.Name = name
+
  End SUb
+

          
+
  ' デシリアライズの際に呼び出されるコンストラクタ
+
  Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
+
    MyClass.ID = info.GetInt32("ID")
+
    MyClass.Name = info.GetString("名前")
+
  End SUb
+

          
+
  ' ISerializable.GetObjectDataの実装
+
  Protected Overridable Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData
+
    ' シリアライズする値を追加する
+
    info.AddValue("ID", ID)
+
    info.AddValue("名前", Name)
+
  End Sub
+
End Class
 

        

        
~
<Serializable> _
        ' シリアル化すべきインスタンス
~
Class Account
        Dim mikitty As New ClassForSerialization("藤本美貴", 18, "A")
+
  Inherits AccountBase
+

          
+
  Public ContactAddresses() As Uri
+

          
+
  Public Sub New(ByVal id As Integer, ByVal name As String)
+
    MyBase.New(id, name)
+
  End SUb
+

          
+
  ' デシリアライズの際に呼び出されるコンストラクタ
+
  Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
+
    MyBase.New(info, context)
+

          
+
    MyClass.ContactAddresses = CType(info.GetValue("連絡先", GetType(Uri())), Uri())
+
  End SUb
+

          
+
  ' GetObjectDataをオーバーライド
+
  Protected Overrides Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext)
+
    ' 基底クラスのシリアライズ情報を取得
+
    MyBase.GetObjectData(info, context)
+

          
+
    info.AddValue("連絡先", ContactAddresses, GetType(Uri()))
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} ContactAddresses={2}", _
+
                         ID, _
+
                         Name, _
+
                         String.Join(", ", Array.ConvertAll(ContactAddresses, AddressOf Convert.ToString)))
+
  End Function
+
End Class
 

        

        
~
Class Sample
        ' ストリームをオープン
~
  Shared Sub Main()
        Dim stream As New FileStream("serialization.xml", FileMode.Create)
+
    Dim alice As New Account(2, "Alice")
 

        

        
~
    alice.ContactAddresses = New Uri() { _
        ' SOAPフォーマッタを作成
~
      New Uri("mailto:alice@mail.example.net"), _
        Dim formatter As New SoapFormatter(Nothing, New StreamingContext(StreamingContextStates.File))
+
      New Uri("http://example.com/~alice/") _
+
    }
 

        

        
~
    Console.WriteLine(alice)
        ' シリアル化
-
        formatter.Serialize(stream, mikitty)
 

        

        
~
    ' シリアライズ
        ' ストリームをクローズ
~
    Using stream As Stream = File.OpenWrite("alice.soap.xml")
        stream.Close()
+
      Dim formatter As New SoapFormatter()
 

        

        
~
      formatter.Serialize(stream, alice)
    End Sub
+
    End Using
 

        

        
~
    ' デシリアライズ
End Module
+
    Using stream As Stream = File.OpenRead("alice.soap.xml")
+
      Dim formatter As New SoapFormatter()
 

        

        
~
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
' シリアル化の対象となるクラス
-
<Serializable()> _
-
Class ClassForSerialization
 

        

        
~
      Console.WriteLine(deserialized)
    ' シリアル化の対象となるメンバ
~
    End Using
    Private name As String
~
  End Sub
    Private age As Integer
~
End Class
    Public BloodType As String
+
}}
+
#tabpage-end
 

        

        
~
#prompt{{
    ' コンストラクタ
~
2:Alice ContactAddresses=mailto:alice@mail.example.net, http://example.com/~alice/
    Public Sub New(ByVal name As String, ByVal age As Integer, ByVal bloodType As String)
+
2:Alice ContactAddresses=mailto:alice@mail.example.net, http://example.com/~alice/
+
}}
 

        

        
~
**デシリアライズ後のコールバック (IDeserializationCallback)
        MyClass.name = name
~
&msdn(netfx,type,System.Runtime.Serialization.IDeserializationCallback){IDeserializationCallbackインターフェイス};もデシリアライズが完了した時点で呼び出されるコールバックメソッドを実装するためのものです。 OnDeserializedAttributeと機能と動作は同じです。 引数としてStreamingContextの代わりにobjectをとりますが、有効な値は渡されないようです。
        MyClass.age = age
-
        MyClass.BloodType = bloodType
 

        

        
~
#tabpage(C#)
    End Sub
+
#code(cs){{
+
using System;
+
using System.IO;
+
using System.Runtime.Serialization;
+
using System.Runtime.Serialization.Formatters.Binary;
 

        

        
~
[Serializable]
    ' ToString()メソッドのオーバーライド
~
class Account : IDeserializationCallback
    Overrides Function ToString() As String
+
{
+
  public int ID;
+
  public string Name;
 

        

        
~
  [NonSerialized]
        Return MyClass.name + "(" + MyClass.age.ToString() + "歳," + MyClass.BloodType + "型)"
+
  private bool deserialized = false;
 

        

        
~
  public override string ToString()
    End Function
+
  {
+
    return string.Format("{0}:{1} {2}", ID, Name, deserialized ? "(deserialized)" : string.Empty);
+
  }
 

        

        
~
  void IDeserializationCallback.OnDeserialization(object sender)
End Class
~
  {
}}
+
    deserialized = true;
 

        

        
~
    Console.WriteLine("OnDeserialization: sender={0}", sender);
#code(xml,出力結果){{
~
  }
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
~
}
<SOAP-ENV:Body>
-
<a1:ClassForSerialization id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Serialization/Serialization%2C%20Version%3D1.0.1257.29895%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
-
<name id="ref-3">藤本美貴</name>
-
<age>18</age>
-
<BloodType id="ref-4">A</BloodType>
-
</a1:ClassForSerialization>
-
</SOAP-ENV:Body>
-
</SOAP-ENV:Envelope>
-
}}
 

        

        
~
class Sample
出力されたXMLファイルを開いてみればわかると思いますが、フィールドのスコープに関わらず、すべてシリアル化されています。  SoapFormatterコンストラクタで指定しているStreamingContext構造体はシリアル化されたオブジェクトの転送元・転送先を指定するためのものです。 ここではファイルに出力するため、StreamingContextStates.Filesを指定しています。 また、シリアル化されたオブジェクトを逆シリアル化するには次のようにします。
+
{
+
  static void Main()
+
  {
+
    Account alice = new Account();
 

        

        
~
    alice.ID = 2;
#code(vb){{
~
    alice.Name = "Alice";
Sub Main()
 

        

        
~
    Console.WriteLine(alice);
    ' 逆シリアル化されるオブジェクト
-
    Dim mikitty As ClassForSerialization
 

        

        
~
    using (Stream stream = File.OpenWrite("alice.bin"))
    ' ストリームをオープン
~
    {
    Dim stream As New FileStream("serialization.xml", FileMode.Open)
+
      BinaryFormatter formatter = new BinaryFormatter();
 

        

        
~
      Console.WriteLine("Serialize");
    ' SOAPフォーマッタを作成
-
    Dim formatter As New SoapFormatter(Nothing, New StreamingContext(StreamingContextStates.File))
 

        

        
~
      formatter.Serialize(stream, alice);
    ' シリアル化
~
    }
    mikitty = CType(formatter.Deserialize(stream), ClassForSerialization)
 

        

        
~
    using (Stream stream = File.OpenRead("alice.bin"))
    ' ストリームをクローズ
~
    {
    stream.Close()
+
      BinaryFormatter formatter = new BinaryFormatter();
 

        

        
~
      Console.WriteLine("Deserialize");
    ' 結果を出力
-
    Console.WriteLine(mikitty)
 

        

        
~
      Account deserialized = (Account)formatter.Deserialize(stream);
End Sub
-
}}
 

        

        
~
      Console.WriteLine(deserialized);
#prompt(実行結果){{
~
    }
藤本美貴(18歳,A型)
+
  }
+
}
 
}}
}}
~
#tabpage(VB)

          
-
*バイナリシリアル化
-
バイナリシリアル化は、その名の通りバイナリ形式でシリアル化します。 シリアル化に際して、インスタンスのメモリ内における実際のビット配置がシリアル化されます。 SOAPシリアル化と比べて非常に高速にシリアル化・逆シリアル化を行うことができます。
-

          
 
#code(vb){{
#code(vb){{
-
Option Strict On
-

          
 
Imports System
Imports System
 
Imports System.IO
Imports System.IO
 
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization
 
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Runtime.Serialization.Formatters.Binary
 

        

        
~
<Serializable> _
Module MainModule
+
Class Account
+
  Implements IDeserializationCallback
 

        

        
~
  Public ID As Integer
    Sub Main()
+
  Public Name As String
 

        

        
~
  <NonSerialized> _
        ' シリアル化すべきインスタンス
~
  Private deserialized As Boolean = False
        Dim mikitty As New ClassForSerialization("藤本美貴", 18, "A")
 

        

        
~
  Public Overrides Function ToString() As String
        ' ストリームをオープン
~
    Return String.Format("{0}:{1} {2}", ID, Name, IIf(deserialized, "(deserialized)", String.Empty))
        Dim stream As New FileStream("serialization.bin", FileMode.Create)
+
  End Function
 

        

        
~
  Private Sub OnDeserialization(ByVal sender As Object) Implements IDeserializationCallback.OnDeserialization
        ' バイナリフォーマッタを作成
~
    deserialized = True
        Dim formatter As New BinaryFormatter(Nothing, New StreamingContext(StreamingContextStates.File))
 

        

        
~
    Console.WriteLine("OnDeserialization: sender={0}", sender)
        ' シリアル化
~
  End Sub
        formatter.Serialize(stream, mikitty)
~
End Class

          
-
        ' ストリームをクローズ
-
        stream.Close()
-

          
-
    End Sub
 

        

        
~
Class Sample
End Module
+
  Shared Sub Main()
+
    Dim alice As New Account()
 

        

        
~
    alice.ID = 2
' シリアル化の対象となるクラス
~
    alice.Name = "Alice"
<Serializable()> _
-
Class ClassForSerialization
 

        

        
~
    Console.WriteLine(alice)
    ' シリアル化の対象となるメンバ
-
    Private name As String
-
    Private age As Integer
-
    Public BloodType As String
 

        

        
~
    Using stream As Stream = File.OpenWrite("alice.bin")
    ' コンストラクタ
~
      Dim formatter As New BinaryFormatter()
    Public Sub New(ByVal name As String, ByVal age As Integer, ByVal bloodType As String)
 

        

        
~
      Console.WriteLine("Serialize")
        MyClass.name = name
-
        MyClass.age = age
-
        MyClass.BloodType = bloodType
 

        

        
~
      formatter.Serialize(stream, alice)
    End Sub
+
    End Using
 

        

        
~
    Using stream As Stream = File.OpenRead("alice.bin")
    ' ToString()メソッドのオーバーライド
~
      Dim formatter As New BinaryFormatter()
    Overrides Function ToString() As String
 

        

        
~
      Console.WriteLine("Deserialize")
        Return MyClass.name + "(" + MyClass.age.ToString() + "歳," + MyClass.BloodType + "型)"
 

        

        
~
      Dim deserialized As Account = CType(formatter.Deserialize(stream), Account)
    End Function
 

        

        
+
      Console.WriteLine(deserialized)
+
    End Using
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt{{
#ref(0.png,出力結果(serialization.bin))
+
2:Alice
+
Serialize
+
Deserialize
+
OnDeserialization: sender=
+
2:Alice (deserialized)
+
}}
 

        

        
~
----
SOAPでの逆シリアル化同様に、シリアル化されたオブジェクトを逆シリアル化するには次のようにします。 基本的に変わっているところはフォーマッタにBinaryFormatterを指定しているところだけです。
 

        

        
~
*XmlSerializerの動作の制御
#code(vb){{
~
ここでは[[XmlSerializer>#XmlSerializer]]を使ってシリアライズする場合の動作の制御について解説します。
Sub Main()
 

        

        
~
**シリアライズ対象からの除外 (XmlIgnoreAttribute)
    ' 逆シリアル化されるオブジェクト
~
&msdn(netfx,type,System.Xml.Serialization.XmlIgnoreAttribute){XmlIgnoreAttribute};を使用すると、フィールドをシリアライズ対象から除外することが出来ます。 XmlSerializerではパブリックなフィールド・プロパティをシリアライズしようとしますが、シリアライズする必要の無いフィールドや実行時のみに使用されるフィールドなどは、この属性を使用することでシリアライズしないようにすることが出来ます。
    Dim mikitty As ClassForSerialization
 

        

        
~
以下の例では、Account.LastLoginフィールドにXmlIgnoreAttributeを付与しています。 デシリアライズ後にAccount.LastLoginフィールドの値が復元されていない点に注目してください。
    ' ストリームをオープン
-
    Dim stream As New FileStream("serialization.bin", FileMode.Open)
 

        

        
~
#tabpage(C#)
    ' バイナリフォーマッタを作成
~
#code(cs){{
    Dim formatter As New BinaryFormatter(Nothing, New StreamingContext(StreamingContextStates.File))
+
using System;
+
using System.IO;
+
using System.Xml;
+
using System.Xml.Serialization;
 

        

        
~
public class Account
    ' シリアル化
~
{
    mikitty = CType(formatter.Deserialize(stream), ClassForSerialization)
+
  public int ID;
+
  public string Name;
 

        

        
~
  [XmlIgnore]
    ' ストリームをクローズ
~
  public DateTime LastLogin;
    stream.Close()
 

        

        
~
  // デフォルトコンストラクタ
    ' 結果を出力
~
  public Account() {}
    Console.WriteLine(mikitty)
 

        

        
~
  public override string ToString()
End Sub
~
  {
}}
+
    return string.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin);
+
  }
+
}
 

        

        
~
class Sample
#prompt(実行結果){{
~
{
藤本美貴(18歳,A型)
~
  static void Main()
}}
+
  {
+
    Account alice = new Account();
 

        

        
~
    alice.ID = 2;
このように、SOAPシリアル化・バイナリシリアル化のいずれでも適切にシリアル化・逆シリアル化が行われ、任意の時点でインスタンスを復元することができます。
+
    alice.Name = "Alice";
+
    alice.LastLogin = new DateTime(2010, 10, 20);
 

        

        
~
    Console.WriteLine(alice);
*NonSerialized属性
-
SOAPシリアル化・バイナリシリアル化では、フィールドのスコープに関係なくすべてのフィールドがシリアル化の対象となっています。 しかし、場合によってはシリアル化したくないフィールドもでてくると思います。 そのような場合にはNonSerialized属性を使用します。 この属性は、シリアル化したくないフィールドの宣言部に指定します。
 

        

        
~
    // シリアライズ
次のコードは先ほどのクラスを多少変えたものです。 誕生日をメンバとして保持するために年齢はこの誕生日から計算すればよいため、このフィールドはシリアル化しないことにします。 シリアル化の方法は先ほど紹介した方法と変わりません。
+
    using (Stream stream = File.OpenWrite("alice.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(alice.GetType());
 

        

        
~
      serializer.Serialize(stream, alice);
#code(vb){{
~
    }
' シリアル化の対象となるクラス
-
<Serializable()> _
-
Class ClassForSerialization
 

        

        
~
    // デシリアライズ
    ' シリアル化の対象となるメンバ
~
    using (Stream stream = File.OpenRead("alice.xml"))
    Public Name As String
~
    {
    Public BloodType As String
~
      XmlSerializer serializer = new XmlSerializer(typeof(Account));
    Public BirthDate As Date
 

        

        
~
      Account deserialized = (Account)serializer.Deserialize(stream);
    ' シリアル化の対象外
-
    <NonSerialized()> Private m_Age As Integer
 

        

        
~
      Console.WriteLine(deserialized);
    Public ReadOnly Property Age() As Integer
~
    }
        Get
~
  }
            ' 誕生日から年齢を計算
~
}
            m_Age = DateTime.Now.Year - BirthDate.Year
~
}}

          
~
#tabpage(VB)
            Dim birthDayInThisYear As New DateTime(DateTime.Now.Year, BirthDate.Month, BirthDate.Day)
+
#code(vb){{
+
Imports System
+
Imports System.IO
+
Imports System.Xml
+
Imports System.Xml.Serialization
 

        

        
~
Public Class Account
            If birthDayInThisYear > DateTime.Now Then m_Age -= 1
+
  Public ID As Integer
+
  Public Name As String
+

          
+
  <XmlIgnore> _
+
  Public LastLogin As DateTime
+

          
+
  ' デフォルトコンストラクタ
+
  Public Sub New()
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin)
+
  End Function
+
End Class
 

        

        
~
Class Sample
            Return m_Age
~
  Shared Sub Main()
        End Get
~
    Dim alice As New Account()
    End Property
 

        

        
~
    alice.ID = 2
    ' コンストラクタ
~
    alice.Name = "Alice"
    Public Sub New(ByVal name As String, ByVal birthDate As Date, ByVal bloodType As String)
+
    alice.LastLogin = New DateTime(2010, 10, 20)
 

        

        
~
    Console.WriteLine(alice)
        MyClass.Name = name
-
        MyClass.BirthDate = birthDate
-
        MyClass.BloodType = bloodType
 

        

        
~
    ' シリアライズ
    End Sub
+
    Using stream As Stream = File.OpenWrite("alice.xml")
+
      Dim serializer As New XmlSerializer(alice.GetType())
 

        

        
~
      serializer.Serialize(stream, alice)
    ' ToString()メソッドのオーバーライド
~
    End Using
    Overrides Function ToString() As String
 

        

        
~
    ' デシリアライズ
        Return MyClass.Name + "(" + MyClass.BirthDate.ToShortDateString() + "生まれ," + _
~
    Using stream As Stream = File.OpenRead("alice.xml")
               MyClass.Age.ToString() + "歳," + MyClass.BloodType + "型)"
+
      Dim serializer As New XmlSerializer(GetType(Account))
 

        

        
~
      Dim deserialized As Account = CType(serializer.Deserialize(stream), Account)
    End Function
 

        

        
+
      Console.WriteLine(deserialized)
+
    End Using
+
  End Sub
 
End Class
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#prompt{{
#code(xml,出力結果){{
~
2:Alice LastLogin=2010/10/20 0:00:00
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
~
2:Alice LastLogin=0001/01/01 0:00:00
<SOAP-ENV:Body>
-
<a1:ClassForSerialization id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Serialization/Serialization%2C%20Version%3D1.0.1257.29895%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
-
<Name id="ref-3">藤本美貴</Name>
-
<BloodType id="ref-4">A</BloodType>
-
<BirthDate>1985-02-26T00:00:00.0000000+09:00</BirthDate>
-
</a1:ClassForSerialization>
-
</SOAP-ENV:Body>
-
</SOAP-ENV:Envelope>
 
}}
}}
 

        

        
~
#code(xml,alice.xmlの内容){{
上のファイルはこのクラスをシリアル化した場合の出力結果の例です。 これを逆シリアル化し、ToString()メソッドを呼び出してメンバの値を確認すると、次のようになります。
~
<?xml version="1.0"?>

          
~
<Account xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
#prompt(実行結果){{
~
  <ID>2</ID>
藤本美貴(1985/02/26生まれ,18歳,A型)
+
  <Name>Alice</Name>
+
</Account>
 
}}
}}
 

        

        
~
**クラス・フィールドのXML要素名の指定 (XmlElementAttribute, XmlTypeAttribute, XmlRootAttribute)
*ISerializableインターフェイスによるシリアル化のカスタマイズ
~
&msdn(netfx,type,System.Xml.Serialization.XmlElementAttribute){XmlElementAttribute};の&msdn(netfx,member,System.Xml.Serialization.XmlElementAttribute.ElementName){ElementName};を指定することで、シリアライズの際に出力されるフィールドのXML要素の名前を指定することが出来ます。 この属性を指定しない場合は、フィールド名が要素名のデフォルトとして使用されます。
ISerializableインターフェイスを使用すると、シリアル化の動作を制御できます。 ISerializableインターフェイスには GetObjectData()というメソッドが一つだけあるので、独自のシリアル化処理を行うには、対象のクラスにこのメソッドを実装するだけです。 このメソッドでは、シリアル化に関する情報(シリアル化する値と、それに関連づける名前)を追加します。 また、これとは別に二つのコンストラクタを用意する必要があります。
-

          
-
一つは、インスタンスを生成するために必要な既定のコンストラクタで、もう一つはシリアル化情報を元にインスタンスの各フィールドの値を初期化するための暗黙のコンストラクタです。 これらをすべて実装し、独自のシリアル化を行うためのクラスのサンプルを次に示します。 基本的には先ほどから使用してきたクラスと同じ構造ですが、シリアル化に関する追加的なコードに注目してください。
-

          
-
#code(vb){{
-
' シリアル化の対象となるクラス
-
<Serializable()> _
-
Class ClassForSerialization
-

          
-
    ' ISerializableをインプリメント
-
    Implements ISerializable
-

          
-
    ' 各フィールド
-
    Public Name As String
-
    Public BloodType As String
-
    Public BirthDate As Date
-
    Private m_Age As Integer
-

          
-
    Public ReadOnly Property Age() As Integer
-
        Get
-
            ' 誕生日から年齢を計算
-
            m_Age = DateTime.Now.Year - BirthDate.Year
 

        

        
~
また、&msdn(netfx,type,System.Xml.Serialization.XmlTypeAttribute){XmlTypeAttribute};の&msdn(netfx,member,System.Xml.Serialization.XmlTypeAttribute.TypeName){TypeName};もしくは&msdn(netfx,type,System.Xml.Serialization.XmlRootAttribute){XmlRootAttribute};の&msdn(netfx,member,System.Xml.Serialization.XmlRootAttribute.ElementName){ElementName};を指定することで、型のXML要素の名前を指定することが出来ます。 この属性を指定しない場合は、型名が要素名のデフォルトとして使用されます。 XmlRootAttributeとXmlTypeAttributeの違いは、XmlRootAttributeは型がルート要素となったときの要素名を指定するのに対し、XmlTypeAttributeは型がルート要素となるかどうかに関わらず要素名を指定するという点です。 なお、これらのプロパティはいずれも、名前付きパラメータとして指定することも属性のコンストラクタで指定することも出来ます。
            Dim birthDayInThisYear As New DateTime(DateTime.Now.Year, BirthDate.Month, BirthDate.Day)
 

        

        
~
以下の例では、AccountクラスにXmlRootAttribute、Account.NameフィールドとLastLoginフィールドにXmlElementAttributeを付与しています。 シリアライザが出力するXMLファイルの要素名が指定した名前に変わっている点に注目してください。
            If birthDayInThisYear > DateTime.Now Then m_Age -= 1
 

        

        
~
#tabpage(C#)
            Return m_Age
~
#code(cs){{
        End Get
~
using System;
    End Property
+
using System.IO;
+
using System.Xml;
+
using System.Xml.Serialization;
 

        

        
~
[XmlRoot("アカウント情報")]
    ' 通常のコンストラクタ
~
public class Account
    Public Sub New(ByVal name As String, ByVal birthDate As Date, ByVal bloodType As String)
+
{
+
  public int ID;
 

        

        
~
  [XmlElement("名前")]
        MyClass.Name = name
~
  public string Name;
        MyClass.BirthDate = birthDate
-
        MyClass.BloodType = bloodType
 

        

        
~
  [XmlElement("最終ログイン日時")]
    End Sub
+
  public DateTime LastLogin;
 

        

        
~
  // デフォルトコンストラクタ
    ' 逆シリアル化に必要な既定のコンストラクタ
~
  public Account() {}
    Public Sub New()
-
    End Sub
 

        

        
~
  public override string ToString()
    ' 逆シリアル化に必要な暗黙のコンストラクタ
~
  {
    Private Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
+
    return string.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin);
+
  }
+
}
 

        

        
~
class Sample
        ' シリアル化情報から値を逆シリアル化された値を取得します
~
{
        MyClass.Name = info.GetString("名前")
~
  static void Main()
        MyClass.BloodType = info.GetString("血液型")
~
  {
        MyClass.BirthDate = info.GetDateTime("誕生日")
+
    Account alice = new Account();
 

        

        
~
    alice.ID = 2;
    End Sub
+
    alice.Name = "Alice";
+
    alice.LastLogin = new DateTime(2010, 10, 20);
 

        

        
~
    Console.WriteLine(alice);
    ' GetObjectData()メソッドの実装
-
    Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) Implements ISerializable.GetObjectData
 

        

        
~
    // シリアライズ
        ' シリアル化情報に、シリアル化に際して値に関連づけられる名称と、その値を追加します
~
    using (Stream stream = File.OpenWrite("alice.xml"))
        info.AddValue("名前", MyClass.Name)
~
    {
        info.AddValue("血液型", MyClass.BloodType)
~
      XmlSerializer serializer = new XmlSerializer(alice.GetType());
        info.AddValue("誕生日", MyClass.BirthDate)
 

        

        
~
      serializer.Serialize(stream, alice);
    End Sub
+
    }
 

        

        
~
    // デシリアライズ
    ' ToString()メソッドのオーバーライド
~
    using (Stream stream = File.OpenRead("alice.xml"))
    Overrides Function ToString() As String
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(Account));
 

        

        
~
      Account deserialized = (Account)serializer.Deserialize(stream);
        Return MyClass.Name + "(" + MyClass.BirthDate.ToShortDateString() + "生まれ," + MyClass.Age.ToString() + "歳," + MyClass.BloodType + "型)"
-

          
-
    End Function
-

          
-
End Class
-
}}
 

        

        
~
      Console.WriteLine(deserialized);
#code(xml,出力結果){{
~
    }
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
~
  }
<SOAP-ENV:Body>
~
}
<a1:ClassForSerialization id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/Serialization/Serialization%2C%20Version%3D1.0.1257.29895%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
-
<名前 id="ref-3">藤本美貴</名前>
-
<血液型 id="ref-4">A</血液型>
-
<誕生日 xsi:type="xsd:dateTime">1985-02-26T00:00:00.0000000+09:00</誕生日>
-
</a1:ClassForSerialization>
-
</SOAP-ENV:Body>
-
</SOAP-ENV:Envelope>
 
}}
}}
~
#tabpage(VB)

          
-
シリアル化、逆シリアル化に必要なコードは、先ほどと全く変わりません。 次のコードはその例です。 出力結果のように、適切に逆シリアル化されていることを確認してください。
-

          
 
#code(vb){{
#code(vb){{
~
Imports System
' シリアル化
~
Imports System.IO
Sub Serialize()
+
Imports System.Xml
+
Imports System.Xml.Serialization
 

        

        
~
<XmlRoot("アカウント情報")> _
    ' シリアル化されるオブジェクト
~
Public Class Account
    Dim mikitty As New ClassForSerialization("藤本美貴", New Date(1985, 2, 26), "A")
+
  Public ID As Integer
+

          
+
  <XmlElement("名前")> _
+
  Public Name As String
+

          
+
  <XmlElement("最終ログイン日時")> _
+
  Public LastLogin As DateTime
+

          
+
  ' デフォルトコンストラクタ
+
  Public Sub New()
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin)
+
  End Function
+
End Class
 

        

        
~
Class Sample
    ' ストリームをオープン
~
  Shared Sub Main()
    Dim stream As New FileStream("serialization.xml", FileMode.Create)
+
    Dim alice As New Account()
 

        

        
~
    alice.ID = 2
    ' SOAPフォーマッタを作成
~
    alice.Name = "Alice"
    Dim formatter As New SoapFormatter(Nothing, New StreamingContext(StreamingContextStates.File))
+
    alice.LastLogin = New DateTime(2010, 10, 20)
 

        

        
~
    Console.WriteLine(alice)
    ' シリアル化
-
    formatter.Serialize(stream, mikitty)
 

        

        
~
    ' シリアライズ
    ' ストリームをクローズ
~
    Using stream As Stream = File.OpenWrite("alice.xml")
    stream.Close()
+
      Dim serializer As New XmlSerializer(alice.GetType())
 

        

        
~
      serializer.Serialize(stream, alice)
End Sub
+
    End Using
 

        

        
~
    ' デシリアライズ
' 逆シリアル化
~
    Using stream As Stream = File.OpenRead("alice.xml")
Sub Deserialize()
+
      Dim serializer As New XmlSerializer(GetType(Account))
 

        

        
~
      Dim deserialized As Account = CType(serializer.Deserialize(stream), Account)
    ' 逆シリアル化されたオブジェクト
-
    Dim mikitty As ClassForSerialization
 

        

        
~
      Console.WriteLine(deserialized)
    ' ストリームをオープン
~
    End Using
    Dim stream As New FileStream("serialization.xml", FileMode.Open)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#code(xml,alice.xmlの内容){{
    ' SOAPフォーマッタを作成
~
<?xml version="1.0"?>
    Dim formatter As New SoapFormatter(Nothing, New StreamingContext(StreamingContextStates.File))
+
<アカウント情報 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
  <ID>2</ID>
+
  <名前>Alice</名前>
+
  <最終ログイン日時>2010-10-20T00:00:00</最終ログイン日時>
+
</アカウント情報>
+
}}
+

          
+
**クラス・フィールドのXML名前空間の指定 (XmlElementAttribute, XmlTypeAttribute, XmlRootAttribute)
+
XML要素名の他に、&msdn(netfx,member,System.Xml.Serialization.XmlElementAttribute.Namespace){XmlElementAttribute.Namespace};、&msdn(netfx,member,System.Xml.Serialization.XmlTypeAttribute.Namespace){XmlTypeAttribute.Namespace};、&msdn(netfx,member,System.Xml.Serialization.XmlRootAttribute.Namespace){XmlRootAttribute.Namespace};を指定することで、シリアライズの際に出力されるXML要素の名前空間を指定することが出来ます。 これらのプロパティはコンストラクタでは指定出来ないため、いずれも名前付きパラメータとして指定する必要があります。 また、これらの属性で指定した名前空間のプレフィックスを制御するには、&msdn(netfx,type,System.Xml.Serialization.XmlSerializerNamespaces){XmlSerializerNamespaces};を使用します。 名前空間のプレフィックスは、XmlSerializer.SerializeメソッドにXmlSerializerNamespacesを指定することで有効になります。
+

          
+
以下の例では、Accountクラスに対して上記の属性を付与し、シリアライズの際のXML名前空間を指定しています。 先の例とは異なり、Listに格納したAccountをシリアライズするため、XmlRootAttributeではなくXmlTypeAttributeを指定しています。 また、XmlSerializerNamespacesを使って名前空間のプレフィックスを指定しています。 シリアライザが出力するXMLファイルの各要素の名前空間が指定した値に変わっている点に注目してください。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Collections.Generic;
+
using System.IO;
+
using System.Xml;
+
using System.Xml.Serialization;
+

          
+
[XmlType("アカウント情報", Namespace = "http://example.com/ns/account")]
+
public class Account
+
{
+
  [XmlElement(Namespace = "http://example.com/ns/account")]
+
  public int ID;
+

          
+
  [XmlElement("名前", Namespace = "http://example.com/ns/account")]
+
  public string Name;
+

          
+
  [XmlElement("最終ログイン日時", Namespace = "http://example.com/ns/account/extensions")]
+
  public DateTime LastLogin;
+

          
+
  // デフォルトコンストラクタ
+
  public Account() {}
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<Account> accounts = new List<Account>();
+

          
+
    accounts.Add(new Account() {ID = 2, Name = "Alice",   LastLogin = new DateTime(2010, 10, 20)});
+
    accounts.Add(new Account() {ID = 0, Name = "Charlie", LastLogin = new DateTime(2010, 11, 20)});
+
    accounts.Add(new Account() {ID = 1, Name = "Eve",     LastLogin = new DateTime(2010, 12, 20)});
+

          
+
    foreach (Account e in accounts)
+
    {
+
      Console.WriteLine(e);
+
    }
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("accounts.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(accounts.GetType());
+
      XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
+

          
+
      ns.Add("ac", "http://example.com/ns/account");
+
      ns.Add("acex", "http://example.com/ns/account/extensions");
+

          
+
      serializer.Serialize(stream, accounts, ns);
+
    }
+

          
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("accounts.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(List<Account>));
+

          
+
      List<Account> deserialized = (List<Account>)serializer.Deserialize(stream);
+

          
+
      Console.WriteLine("[deserialized]");
+

          
+
      foreach (Account e in deserialized)
+
      {
+
        Console.WriteLine(e);
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.IO
+
Imports System.Xml
+
Imports System.Xml.Serialization
+

          
+
<XmlType("アカウント情報", Namespace := "http://example.com/ns/account")> _
+
Public Class Account
+
  <XmlElement(Namespace := "http://example.com/ns/account")> _
+
  Public ID As Integer
+

          
+
  <XmlElement("名前", Namespace := "http://example.com/ns/account")> _
+
  Public Name As String
+

          
+
  <XmlElement("最終ログイン日時", Namespace := "http://example.com/ns/account/extensions")> _
+
  Public LastLogin As DateTime
+

          
+
  ' デフォルトコンストラクタ
+
  Public Sub New()
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin)
+
  End Function
+
End Class
 

        

        
~
Class Sample
    ' 逆シリアル化
~
  Shared Sub Main()
    mikitty = CType(formatter.Deserialize(stream), ClassForSerialization)
+
    Dim accounts As New List(Of Account)
+

          
+
    accounts.Add(New Account() With {.ID = 2, .Name = "Alice",   .LastLogin = New DateTime(2010, 10, 20)})
+
    accounts.Add(New Account() With {.ID = 0, .Name = "Charlie", .LastLogin = New DateTime(2010, 11, 20)})
+
    accounts.Add(New Account() With {.ID = 1, .Name = "Eve",     .LastLogin = New DateTime(2010, 12, 20)})
+

          
+
    For Each e As Account In accounts
+
      Console.WriteLine(e)
+
    Next
+

          
+
    ' シリアライズ
+
    Using stream As Stream = File.OpenWrite("accounts.xml")
+
      Dim serializer As New XmlSerializer(accounts.GetType())
+
      Dim ns As New XmlSerializerNamespaces()
+

          
+
      ns.Add("ac", "http://example.com/ns/account")
+
      ns.Add("acex", "http://example.com/ns/account/extensions")
+

          
+
      serializer.Serialize(stream, accounts, ns)
+
    End Using
+

          
+
    ' デシリアライズ
+
    Using stream As Stream = File.OpenRead("accounts.xml")
+
      Dim serializer As New XmlSerializer(GetType(List(Of Account)))
+

          
+
      Dim deserialized As List(Of Account) = CType(serializer.Deserialize(stream), List(Of Account))
+

          
+
      Console.WriteLine("deserialized")
+

          
+
      For Each e As Account In accounts
+
        Console.WriteLine(e)
+
      Next
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
#code(xml,accounts.xmlの内容){{
    ' ストリームをクローズ
~
<?xml version="1.0"?>
    stream.Close()
+
<ArrayOfアカウント情報 xmlns:ac="http://example.com/ns/account" xmlns:acex="http://example.com/ns/account/extensions">
+
  <アカウント情報>
+
    <ac:ID>2</ac:ID>
+
    <ac:名前>Alice</ac:名前>
+
    <acex:最終ログイン日時>2010-10-20T00:00:00</acex:最終ログイン日時>
+
  </アカウント情報>
+
  <アカウント情報>
+
    <ac:ID>0</ac:ID>
+
    <ac:名前>Charlie</ac:名前>
+
    <acex:最終ログイン日時>2010-11-20T00:00:00</acex:最終ログイン日時>
+
  </アカウント情報>
+
  <アカウント情報>
+
    <ac:ID>1</ac:ID>
+
    <ac:名前>Eve</ac:名前>
+
    <acex:最終ログイン日時>2010-12-20T00:00:00</acex:最終ログイン日時>
+
  </アカウント情報>
+
</ArrayOfアカウント情報>
+
}}
+

          
+
**フィールドを属性としてシリアライズする (XmlAttributeAttribute)
+
フィールドに対して&msdn(netfx,member,System.Xml.Serialization.XmlAttributeAttribute){XmlAttributeAttribute};を指定することで、そのフィールドをXML属性として出力させるようにすることが出来ます。 コンストラクタ・パラメータで指定しなかった場合はデフォルトでフィールド名が属性名となります。 また、&msdn(netfx,member,System.Xml.Serialization.XmlAttributeAttribute.Namespace){Namespace};プロパティを指定することで属性の名前空間を指定することも出来ます。
+

          
+
以下の例では、Account.IDフィールドに対して上記の属性を付与し、シリアライズの際に属性として出力するようにし、また同時に属性の名前も指定しています。 シリアライザが出力するXMLファイルにおいて、Account.IDフィールドの値が属性として出力されている点に注目してください。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Collections.Generic;
+
using System.IO;
+
using System.Xml;
+
using System.Xml.Serialization;
+

          
+
[XmlType("アカウント情報")]
+
public class Account
+
{
+
  [XmlAttribute("アカウントID")]
+
  public int ID;
+

          
+
  [XmlElement("名前")]
+
  public string Name;
+

          
+
  [XmlElement("最終ログイン日時")]
+
  public DateTime LastLogin;
+

          
+
  // デフォルトコンストラクタ
+
  public Account() {}
+

          
+
  public override string ToString()
+
  {
+
    return string.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin);
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    List<Account> accounts = new List<Account>();
+

          
+
    accounts.Add(new Account() {ID = 2, Name = "Alice",   LastLogin = new DateTime(2010, 10, 20)});
+
    accounts.Add(new Account() {ID = 0, Name = "Charlie", LastLogin = new DateTime(2010, 11, 20)});
+
    accounts.Add(new Account() {ID = 1, Name = "Eve",     LastLogin = new DateTime(2010, 12, 20)});
+

          
+
    foreach (Account e in accounts)
+
    {
+
      Console.WriteLine(e);
+
    }
+

          
+
    // シリアライズ
+
    using (Stream stream = File.OpenWrite("accounts.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(accounts.GetType());
+

          
+
      serializer.Serialize(stream, accounts);
+
    }
+

          
+
    // デシリアライズ
+
    using (Stream stream = File.OpenRead("accounts.xml"))
+
    {
+
      XmlSerializer serializer = new XmlSerializer(typeof(List<Account>));
+

          
+
      List<Account> deserialized = (List<Account>)serializer.Deserialize(stream);
+

          
+
      Console.WriteLine("[deserialized]");
+

          
+
      foreach (Account e in deserialized)
+
      {
+
        Console.WriteLine(e);
+
      }
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Collections.Generic
+
Imports System.IO
+
Imports System.Xml
+
Imports System.Xml.Serialization
 

        

        
~
<XmlType("アカウント情報")> _
    ' インスタンスの値を表示
~
Public Class Account
    Console.WriteLine(mikitty)
+
  <XmlAttribute("アカウントID")> _
+
  Public ID As Integer
+

          
+
  <XmlElement("名前")> _
+
  Public Name As String
+

          
+
  <XmlElement("最終ログイン日時")> _
+
  Public LastLogin As DateTime
+

          
+
  ' デフォルトコンストラクタ
+
  Public Sub New()
+
  End Sub
+

          
+
  Public Overrides Function ToString() As String
+
    Return String.Format("{0}:{1} LastLogin={2}", ID, Name, LastLogin)
+
  End Function
+
End Class
 

        

        
~
Class Sample
End Sub
+
  Shared Sub Main()
+
    Dim accounts As New List(Of Account)
+

          
+
    accounts.Add(New Account() With {.ID = 2, .Name = "Alice",   .LastLogin = New DateTime(2010, 10, 20)})
+
    accounts.Add(New Account() With {.ID = 0, .Name = "Charlie", .LastLogin = New DateTime(2010, 11, 20)})
+
    accounts.Add(New Account() With {.ID = 1, .Name = "Eve",     .LastLogin = New DateTime(2010, 12, 20)})
+

          
+
    For Each e As Account In accounts
+
      Console.WriteLine(e)
+
    Next
+

          
+
    ' シリアライズ
+
    Using stream As Stream = File.OpenWrite("accounts.xml")
+
      Dim serializer As New XmlSerializer(accounts.GetType())
+

          
+
      serializer.Serialize(stream, accounts)
+
    End Using
+

          
+
    ' デシリアライズ
+
    Using stream As Stream = File.OpenRead("accounts.xml")
+
      Dim serializer As New XmlSerializer(GetType(List(Of Account)))
+

          
+
      Dim deserialized As List(Of Account) = CType(serializer.Deserialize(stream), List(Of Account))
+

          
+
      Console.WriteLine("deserialized")
+

          
+
      For Each e As Account In accounts
+
        Console.WriteLine(e)
+
      Next
+
    End Using
+
  End Sub
+
End Class
 
}}
}}
+
#tabpage-end
 

        

        
~
#code(xml,accounts.xmlの内容){{
#prompt(実行結果){{
~
<?xml version="1.0"?>
藤本美貴(1985/02/26生まれ,18歳,A型)
+
<ArrayOfアカウント情報 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
  <アカウント情報 アカウントID="2">
+
    <名前>Alice</名前>
+
    <最終ログイン日時>2010-10-20T00:00:00</最終ログイン日時>
+
  </アカウント情報>
+
  <アカウント情報 アカウントID="0">
+
    <名前>Charlie</名前>
+
    <最終ログイン日時>2010-11-20T00:00:00</最終ログイン日時>
+
  </アカウント情報>
+
  <アカウント情報 アカウントID="1">
+
    <名前>Eve</名前>
+
    <最終ログイン日時>2010-12-20T00:00:00</最終ログイン日時>
+
  </アカウント情報>
+
</ArrayOfアカウント情報>
 
}}
}}
 

        

        
~
**その他のシリアライズ動作の制御
このように、ISerializableと適切なコンストラクタを使用すると、NonSerialized属性を使用しなくてもシリアル化の是非を決定できるのは言うまでもなく、シリアル化に際しての動作をカスタマイズすることができます。
+
XmlSerializerでもISerializableを使ったシリアライズ動作の制御を行うことが出来ます。 詳しくは[[ISerializableの解説>#ISerializable]]を参照してください。
+

          
+
また、ここまでで解説した以外にもシリアライズのための属性が存在します。 詳しくは以下のドキュメントを参照してください。
 

        

        
~
-&msdn(netfx,id,2baksw0z){属性を使用した XML シリアル化の制御};
ここではSOAPシリアル化でISerializableを使用するサンプルを挙げましたが、XMLシリアル化やバイナリシリアル化でも全く同じようにシリアル化できるので、シリアル化制御とシリアル化方法を場合に応じて適切に使い分けることができます。
+
-&msdn(netfx,id,83y7df3e){XML シリアル化を制御する属性};