連載

.NETで簡単XML

第11回 オブジェクトをXMLでシリアライズ(3)

株式会社ピーデー 川俣 晶
2003/11/22

Back Issue
1
XML超入門
2 プログラムでXML文書を作成する
3 XML文書を読み書きするプログラムの作成
4 DOM(Document Object Model)

5

DOMとXPath

6

.NETプログラムでXSLTスクリプトを使う

7

VS.NETでXML Schemaを活用する(作成編)
8 VS.NETでXML Schemaを活用する(動作編)
9 オブジェクトをXMLでシリアライズ(1)
10 オブジェクトをXMLでシリアライズ(2)

今回のサンプル・プログラムについて

 今回もサンプル・プログラムは、Visual Basic .NET(以下VB.NET)とC#で記述したものを用意した。VB.NETのサンプルを掲載するとともに、VB.NET、C#それぞれへのサンプルのリンクを張ってあるので、必要に応じてダウンロードしてほしい。開発環境としてはVisual Studio .NET 2003を使用することを前提にしている。

 サンプル・プログラムはすべてWindowsアプリケーションとしてプロジェクトを作成後に、フォームのLoadイベントに実行するコードを書き込み、Trace.WriteLineメソッドで結果を出力する。結果の確認は、統合開発環境(IDE)の出力ウィンドウで行う。ただし、クラスだけはフォームのクラス外に別途記述する必要がある。それぞれのソースの先頭には、以下のコードが書かれているものとする。

Imports System.IO
Imports System.Xml.Serialization
VB.NETの場合
 
using System.IO;
using System.Xml.Serialization;
C#の場合

はじめに

 前回は、System.Xml.Serialization.XmlSerializerクラスを使用した、オブジェクトのシリアライズ入門を解説した。オブジェクトのシリアライズ(シリアル化とも呼ばれる)とは、インスタンスの内容を1列のデータの列に置き換える処理であり、オブジェクトをファイルに保存したり、通信回線で送る際に必要とされる機能である。今回は、System.Xml.Serialization.XmlSerializerクラスを使用したシリアライズについてより深く解説していきたいと思う。

派生クラスを含む配列のシリアライズ

 配列も容易にシリアライズできることは、前回の「配列のシリアル化」で解説した。しかし、ここには1つの罠が待ち構えている。オブジェクトの配列を宣言するのは容易であり、配列の要素の型を指定することは可能である。ただし、その配列に入っているオブジェクトの型が、常に「配列の要素の型」として指定された型と一致しているわけではない。もちろん、無関係な型の参照を代入しようとすれば、それはエラーになる。だが、「配列の要素の型」として指定されたクラスに対する派生クラスのインスタンスへの参照を代入することは、エラーにならない正常な使い方のうちである。これは、ポリモーフィズム、多態性と呼ばれるテクニックを使うと、必然的に起こる状況である。しかし、このような配列をそのままシリアライズすることはできない。

 例えば、前回の「配列のシリアル化」のサンプル・プログラムに、Personクラスを継承した新しいクラスを追加し、そのクラスのインスタンスを配列に入れるように変更してから実行すると、以下のような例外が発生してしまう。

'System.InvalidOperationException' のハンドルされていない例外が system.xml.dll で発生しました。

 このような状況に対処するには、XmlArrayItem属性(System.Xml.Serialization.XmlArrayItemAttributeクラス)を使う。次に示すのは、実際にXmlArrayItem属性を使用して、ポリモーフィズムを用いた配列を含むクラスをシリアライズした例である。

 まず、シリアライズされる対象となるクラスを見てみよう。これは、ポリモーフィズムを実現するために、継承関係にある3つのクラスと、それらのクラスの配列を含むクラスの、計4クラスから成っている。

Public Class Person
  Private m_name As String = "未設定"
  Public Property Name() As String
    Get
      Return m_name
    End Get
    Set(ByVal Value As String)
      m_name = Value
    End Set
  End Property
End Class

Public Class Child
  Inherits Person
  Private m_schoolName As String = "未設定"
  Public Property SchoolName() As String
    Get
      Return m_schoolName
    End Get
    Set(ByVal Value As String)
      m_schoolName = Value
    End Set
  End Property
End Class

Public Class Adult
  Inherits Person
  Private m_companyName As String = "未設定"
  Public Property CompanyName() As String
    Get
      Return m_companyName
    End Get
    Set(ByVal Value As String)
      m_companyName = Value
    End Set
  End Property
End Class

Public Class Persons
  <XmlArrayItem(Type:=GetType(Child)), _
  XmlArrayItem(Type:=GetType(Adult))> _
  Public persons(2) As Person

  Public Sub SetPersons(ByVal person1 As Person, ByVal person2 As Person, ByVal person3 As Person)
    persons(0) = person1
    persons(1) = person2
    persons(2) = person3
  End Sub

  Public Sub Dump()
    For Each person As Person In persons
      System.Diagnostics.Trace.WriteLine(person.Name)
      If TypeOf person Is Child Then
        System.Diagnostics.Trace.WriteLine(CType(person, Child).SchoolName)
      Else
        System.Diagnostics.Trace.WriteLine(CType(person, Adult).CompanyName)
      End If
    Next
  End Sub
End Class
サンプル・プログラム1-1:シリアライズの対象となるクラス(VB.NET版C#版
 

 INDEX
  .NETで簡単XML
  第11回 オブジェクトをXMLでシリアライズ(3)
  1.派生クラスを含む配列のシリアライズ
    2.派生クラスを含む配列をシリアライズするプログラムの内容
    3.要素のシーケンスとしての配列のシリアライズ
    4.ArrayListオブジェクトのシリアライズ
    5.自作コレクションのシリアライズ
 
インデックス・ページヘ  「連載 :.NETで簡単XML」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間