伊勢的新常識  Index  Search  Changes  RSS  Login

XmlSerializer について

序論

XmlSerializer とは

XmlSerializer は、クラスのインスタンスをXML化して出力したり、出力したXMLを元にインスタンスを復元したりします。

出力の対象となるのはパブリックなプロパティとフィールドです。

複雑なデータ型も独自のファイルの読み書きを実装をせずとも利用できるため、非常に便利なクラスです。

XmlSerializer のメリット

  • 設定などのデータの読み書きを数行のコードで実装できる

XmlSerializer のデメリット・欠点

  • Hashtable など、IDictionary を実装するものはシリアライズできない
  • 配列の配列、ListのListなど、配列の入れ子がある場合はシリアライズできない
  • すべてプリミティブなデータになってしまうため、参照は利用できない。まず、以下のようなコードを書きます。
public class MyClass{
   public string Data;
}

class MainClass{

   [STAThread]
   static void Main(string[] args){
      // データ格納クラスを初期化
      MyClass my = new MyClass();
      my.Data    = "テスト";
      // その配列を作る。
      MyClass myarray = new MyClass {my, my};

      // で、そのDataは同じか。
      if(myarray[0].Data == myarray[1].Data){
         // 全く同じインスタンスなんだから、こっちに流れるのが普通
         Console.WriteLine("作成されたデータの内容は同じ。");
      }else{
         Console.WriteLine("作成されたデータの内容は違う。");
      }

      // 内容を変更してみる。
      my.Data = "テスト2";
      // で、そのDataは同じか。
      if(myarray[0].Data == myarray[1].Data){
         // 全く同じインスタンスなんだから、こっちに流れるのが普通
         Console.WriteLine("変更されたデータの内容は同じ。");
      }else{
         Console.WriteLine("変更されたデータの内容は違う。");
      }

      // シリアライズ
      XmlSerializer serializer       = new XmlSerializer(typeof(MyClass[]));
      System.IO.FileStream outstream = new System.IO.FileStream(@"C:\test.xml", System.IO.FileMode.Create);
      serializer.Serialize(outstream, myarray);
      outstream.Close();
      Console.WriteLine("シリアライズしました。");
      // 一度データをクリア
      my = null;
      myarray = null;
      // デシリアライズ
      System.IO.FileStream instream = new System.IO.FileStream(@"C:\test.xml", System.IO.FileMode.Open);
      myarray = (MyClass[]) serializer.Deserialize(instream);
      instream.Close();
      Console.WriteLine("デシリアライズしました。");

      // で、そのDataは同じか。
      if(myarray[0].Data == myarray[1].Data){
         Console.WriteLine("読み込まれたデータの内容は同じ。");
      }else{
         Console.WriteLine("読み込まれたデータの内容は違う。");
      }

      // 内容を変更してみる。
      myarray[0].Data = "テスト3";
      // これはどうなる?
      if(myarray[0].Data == myarray[1].Data){
         Console.WriteLine("読み込まれて変更されたデータの内容は同じ。");
      }else{
         Console.WriteLine("読み込まれて変更されたデータの内容は違う。");
      }
   }
}

この結果はこうなります。

作成されたデータの内容は同じ。
変更されたデータの内容は同じ。
シリアライズしました。
デシリアライズしました。
読み込まれたデータの内容は同じ。
読み込まれて変更されたデータの内容は違う。

シリアライズ(書き出し)の方法

デシリアライズ(読み込み)の方法

出力されるデータ

たとえば、以下のようなクラスがあったとします。

public class Person
{
	public string Name;
	public int    Age;
}

これをシリアライズするとこうなります

<?xml version="1.0"?>
<Person>
	<Name>名前</Name>
	<Age>14</Age>
</Person>

出力されるXMLコードのコントロール

たとえば、上記のPersonのNameは属性にしたい、出力されるXMLのタグの名前を変えたいということがあります。

このようなときは、Xml〜Attribute をクラスやプロパティなどにつけます。以下の「逆引き属性リファレンス」で詳しく取り上げます

逆引き属性リファレンス

出力されるXMLの形から逆引きする、属性の打ち方リファレンス。

出力される名前を変える

<本>
	<名前>C#の本</名前>
</本>
[XmlType("本")]
public class book
{
	[XmlElement("名前")]
	public string name;
}

属性にする

<bookshelf name="伊勢の本棚">
<books>
	<book name="C#の本" />
	<book name="VB.NETの本" />
</books>
</bookshelf>
public class bookshelf
{
	[XmlAttribute]
	public string     name;
	public List<book> books;
}
public class book
{
	[XmlAttribute]
	public string name;
}

空の項目を許容する

<books>
</books>
[XmlElement(IsNullable = true)]
public List<book> books;

配列・リストを入れ子にしない

<bookshelf>
	<name>伊勢の本棚</name>
	<book>
		<name>C#の本</name>
	</book>
	<book>
		<name>VB.NETの本</name>
	</book>
<bookshelf>

配列・リストに XmlElementAttribute をつけるだけ。

public class bookshelf
{
	public string     name;
	[XmlElement()]
	public List<book> books;
}
public class book
{
	public string name;
}

テキストとして展開する

<book>C#の本</book>
public class book
{
	[XmlText]
	public string name;
}

Last modified:2007/09/17 02:33:57
Keyword(s):
References:[技術ドキュメント] [SideMenu]