連載

.NETで簡単XML

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

株式会社ピーデー 川俣 晶
2004/01/21
Page1 Page2 Page3

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)
11
オブジェクトをXMLでシリアライズ(3)
12 オブジェクトをXMLでシリアライズ(4)

今回および次回のサンプル・ソースについて

 今回から次回にかけてのサンプル・ソースは、Visual Basic .NET(以下VB.NET)とC#を用いて記述してある(編集注:ただし、C#のコードはページ内には表示せず、ファイルとして提供している)。ほぼ同じ内容のものが、2つのプログラム言語で記述されている。開発環境としてはVisual Studio.NET 2003(以下VS.NET)を使用することを前提にしている。

 サンプル・ソースは、Windowsアプリケーションのプロジェクトを作成して、サンプル・ソースのコードをフォームのLoadイベントに書き込み(ただしクラスだけはフォームのクラス外に別途記述する必要がある)、それをビルドして実行すれば、Trace.WriteLineメソッドによって実行結果が出力され、それを統合開発環境の出力ウィンドウで確認できるようになっている。1つだけ例外的に、ASP.NET Webサービスのプロジェクトを作成するが、それについてはその個所で説明を加えている。

 なお、Privateメンバの名前がVB.NET版とC#版では異なっているので、結果が完全に同じにならないケースがある。PublicメンバとPrivateメンバの名前が重複する場合、VB.NET版ではPrivateメンバの名前の先頭の1文字を小文字に変えた上で、先頭に“m_”を付けているが、C#版では先頭の1文字を小文字に変えるだけで対応している。VB.NETは大文字小文字が違うだけのキーワードは同じ名前と見なすが、C#は見なさないという相違によるものである。フィールド名がXML文書に出力されているケースでは、この理由により、結果が同じにならない場合がある。本稿はVB.NETを基準に解説を進めているので、C#プログラマは注意していただきたい。

 もう1つ、今回の原稿の中では、「エンコード済みSOAP形式」を単純に「SOAP形式」とだけ記述している場合があることをお断りしておく。

始めに

 これまで数回にわたって、XMLを用いたオブジェクトのシリアライズについて述べてきたが、まだこれで話は終わりにならない。これまでも、深いところまで踏み込まず、すべての機能を網羅して解説してきたわけではない。それでも、まだ解説すべきことが残っているわけである。

 残された話題は、主に2つである。1つは、XmlSerializerクラスではなく、SoapFormatterクラスを用いたシリアライズについてである。同じシリアライズという処理を行うだけなのに、.NET Frameworkに異なる2つのクラスが存在する理由は、実際に使ってみると分かる。機能性がまったく違うのである。

 もう1つの話題は、少しややこしいことなのだが、XML Webサービスを使う場合に必要とされる知識である。XML Webサービスでは、そのクライアントとの間でオブジェクトを受け渡すこともできるが、その際、オブジェクトはシリアライズされて送受信される。適切にオブジェクトの受け渡しが実施されるためには、受け渡されるクラスが適切にシリアライズ可能な形になっていなければならない。この連載では、XML Webサービスを大きく取り上げるわけではないが、この話題に限ってはシリアライズの問題であるので、解説を行う。

SoapFormatterを使ったシリアライズ

 すでに述べたとおり、.NET Frameworkには、オブジェクトをXML文書にシリアライズする手段として、XmlSerializerクラス(System.Xml.Serialization名前空間)のほかに、SoapFormatterクラス(System.Runtime.Serialization.Formatters.Soap名前空間)が存在する。この2つのクラスは、まったく異なる性格を持っているのだが、何はともあれ、まずはそれを使ってみることから始めよう。

 では、本連載第9回でXmlSerializerクラスを最初に紹介したときのサンプル・プログラムを、SoapFormatterクラスを使うように書き換えてみよう。書き換えた結果は以下のようになる。

 なお、プログラムの先頭には、以下のコードが書かれているものとする。

Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Soap
サンプル・プログラム1-1:SoapFormatterクラスを使用したシリアライズのソースの先頭に必要なコード(VB.NET版C#版

 また、VS.NETのメニュー・バーで[プロジェクト]−[参照の追加]を選び、「System.Runtime.Serialization.Formatters.Soap.dll」をプロジェクトに追加しておく必要がある。ファイル名からも分かるように、SoapFormatterクラスはこのファイルで実装されている。

 さて、次は、シリアライズの対象となるクラスのソース・コードである。

<Serializable()> _
Public Class Person
  Private m_name As String = "未設定"
  Private m_address As String = "未設定"
  Public Age As Integer = 0
  Private m_temporaryID 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
  Public ReadOnly Property Address() As String
    Get
      Return m_address
    End Get
  End Property
  Public Sub SetTemporaryID(ByVal temporaryID As String)
    m_temporaryID = temporaryID
  End Sub
  Public Sub Dump()
    System.Diagnostics.Trace.WriteLine(m_name)
    System.Diagnostics.Trace.WriteLine(m_address)
    System.Diagnostics.Trace.WriteLine(Age)
    System.Diagnostics.Trace.WriteLine(m_temporaryID)
  End Sub
End Class
サンプル・プログラム1-2:SoapFormatterクラスによりシリアライズするPersonクラス(VB.NET版C#版

 次に、このクラスのインスタンスをシリアライズ、デシリアライズする部分は以下のようになる。

Private Sub serializeSample()
  Dim person As Person = New Person
  person.Name = "山田太郎"
  person.Age = 17
  person.SetTemporaryID(DateTime.Now.ToString())

  Dim formatter As SoapFormatter = New SoapFormatter
  Dim stream As Stream = New FileStream("c:\sample.xml", FileMode.Create)
  Try
    formatter.Serialize(Stream, person)
  Finally
    stream.Close()
  End Try
End Sub

Private Sub deserializeSample()
  Dim formatter As SoapFormatter = New SoapFormatter
  Dim person As Person
  Dim stream As Stream = New FileStream("c:\sample.xml", FileMode.Open)
  Try
    person = CType(formatter.Deserialize(stream), Person)
  Finally
    stream.Close()
  End Try
  person.Dump()
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  serializeSample()
  deserializeSample()
End Sub
サンプル・プログラム1-3:SoapFormatterクラスを使用したシリアライズ/デシリアライズ(VB.NET版C#版

 これを実行すると、統合開発環境の出力ウィンドウに以下のような出力が得られる。

山田太郎
未設定
17
2003/12/07 17:20:59
サンプル・プログラム1-3の出力結果
シリアライズしたクラスをさらにデシリアライズしてクラスを生成し、そのクラスのフィールドを統合開発環境の出力ウィンドウに出力した結果。

 また、シリアライズの結果として以下のような内容のXMLファイルが「c:\sample.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:Person id="ref-1" xmlns:a1=
"http://schemas.microsoft.com/clr/nsassem/
VBSample016/VBSample016%2C%20Version%3D1.0.1436.29724%2C%20
Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<m_name id="ref-3">山田太郎</m_name>
<m_address id="ref-4">未設定</m_address>
<Age>17</Age>
<m_temporaryID id="ref-5">2003/12/07 17:20:59</m_temporaryID>
</a1:Person>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SoapFormatterクラスによって生成されたXML文書

 まず、シリアライズされるクラスのソース・コード(本稿の「サンプル・プログラム1-2」)を見てみよう。元になったサンプル・ソース(本連載第9回の「サンプル・プログラム1-1(VB.NET版C#版)」)と、ほとんど差がないことが分かるだろう。シリアライズされるクラスは、先頭に属性を1つ追加した程度の相違でしかない。シリアライズするコード(本稿の「サンプル・プログラム1-3」)も、XmlSerializerクラスの代わりにSoapFormatterクラスを使っているだけで、元のコード(本連載第9回の「サンプル・プログラム1-2(VB.NET版C#版)」)と大差ないように見える。

 しかし実行結果を見比べると、おどろくほど結果が違っていることが分かるだろう。出力結果の4行目は、XmlSerializerクラスを使用したサンプル・ソース(本連載第9回の「サンプル・プログラム1-2の出力」を参照)では「未設定」となっていたが、このサンプル・ソース(本稿の「サンプル・プログラム1-3の出力結果」)では「2003/12/07 17:20:59」という値が出力されている(この値は実行するたびに変わる)。これは、XmlSerializerクラスではシリアライズの対象となっていなかった値が、SoapFormatterではシリアライズの対象とされたことを意味する。

 もう1つの相違点は、シリアライズされた結果となるXML文書の内容(本稿の「SoapFormatterクラスによって生成されたXML文書」と本連載第9回の「生成されたXML文書」を参照)がまったく異なっていることが分かるだろう。


 INDEX
  .NETで簡単XML
  第13回 オブジェクトをXMLでシリアライズ(5)
  1.SoapFormatterを使ったシリアライズ
    2.シリアライズさせないフィールド
    3.SoapFormatterの姉妹クラス、BinaryFormatterクラス
 
インデックス・ページヘ  「連載 :.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 記事ランキング

本日 月間