DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

DOBON.NET

ArrayListオブジェクトの内容をXMLファイルに保存する

先に「クラス、配列などの内容をXMLファイルに保存、復元する」方法を紹介しましたが、ArrayListオブジェクト(または、Object配列など)を同じようにXMLファイルに保存しようとすると、「'System.InvalidOperationException' のハンドルされていない例外が system.xml.dll で発生しました。追加情報 : XML ドキュメントを生成中にエラーが発生しました。」というエラーが発生します。例えば、次のようなケースです。

[VB.NET]
'XMLファイルに保存するオブジェクトのためのクラス
Public Class SampleClass
    Public ClassList As New ArrayList

    Public Sub New()
        'ArrayListにSampleClass2オブジェクトを追加する
        Dim myClass2 As New SampleClass2
        myClass2.Number = 1
        myClass2.Message = "string"
        ClassList.Add(myClass2)
    End Sub
End Class

Public Class SampleClass2
    Public Number As Integer
    Public Message As String
End Class

Class MainClass
    'エントリポイント
    Public Shared Sub Main()
        '保存するSampleClassオブジェクトを作成
        Dim myClasses As New SampleClass

        'XMLファイルに保存する
        Dim serializer As _
            New System.Xml.Serialization.XmlSerializer( _
                GetType(SampleClass))
        Dim fs As New System.IO.FileStream( _
            "C:\test.xml", System.IO.FileMode.Create)
        'エラーが発生する
        serializer.Serialize(fs, myClasses)
        '閉じる
        fs.Close()
    End Sub
End Class
[C#]
//XMLファイルに保存するオブジェクトのためのクラス
public class SampleClass
{
    public ArrayList ClassList = new ArrayList();
    public SampleClass()
    {
        //ArrayListにSampleClass2オブジェクトを追加する
        SampleClass2 myClass2 = new SampleClass2();
        myClass2.Number = 1;
        myClass2.Message = "string";
        ClassList.Add(myClass2);
    }
}

public class SampleClass2
{
    public int Number;
    public string Message;
}

class MainClass
{
    //エントリポイント
    public static void Main()
    {
        //保存するSampleClassオブジェクトを作成
        SampleClass myClasses = new SampleClass();

        //XMLファイルに保存する
        System.Xml.Serialization.XmlSerializer serializer =
            new System.Xml.Serialization.XmlSerializer(
                typeof(SampleClass));
        System.IO.FileStream fs =
            new System.IO.FileStream(@"C:\test.xml",
                System.IO.FileMode.Create);
        //エラーが発生する
        serializer.Serialize(fs, myClasses);
        //閉じる
        fs.Close();
    }
}

XmlSerializerコンストラクタに型を指定する方法

このエラーを回避するためには、次のようにしてXmlSerializerのコンストラクタでArrayListに挿入される可能性のあるすべてのオブジェクトの型を通知する必要があります。つまり上記の例では、ArrayListに挿入されるSampleClass2クラス型を通知します。復元する時も同様にType配列を指定する必要があります。

これに基づき、上記の例を修正すると次のようになります。(SampleClass、SampleClass2の内容は前と同じです。)

[VB.NET]
Class MainClass
    'エントリポイント
    Public Shared Sub Main()
        '保存するSampleClassオブジェクトを作成
        Dim myClasses As New SampleClass

        'ArrayListに挿入できるオブジェクト型のType配列を作成
        Dim et() As Type = {GetType(SampleClass2)}

        'ArrayListに挿入できるオブジェクトを指定して
        'XMLファイルに保存する
        Dim serializer As _
            New System.Xml.Serialization.XmlSerializer( _
                GetType(SampleClass), et)
        Dim fs As New System.IO.FileStream( _
            "C:\test.xml", System.IO.FileMode.Create)
        serializer.Serialize(fs, myClasses)
        '閉じる
        fs.Close()
    End Sub
End Class
[C#]
class MainClass
{
    //エントリポイント
    public static void Main()
    {
        //保存するSampleClassオブジェクトを作成
        SampleClass myClasses = new SampleClass();

        //ArrayListに挿入できるオブジェクト型のType配列を作成
        Type[] et = new Type[] {typeof(SampleClass2)};

        //ArrayListに挿入できるオブジェクトを指定して
        //XMLファイルに保存する
        System.Xml.Serialization.XmlSerializer serializer =
            new System.Xml.Serialization.XmlSerializer(
                typeof(SampleClass), et);
        System.IO.FileStream fs =
            new System.IO.FileStream(@"C:\test.xml",
                System.IO.FileMode.Create);
        serializer.Serialize(fs, myClasses);
        //閉じる
        fs.Close();
    }
}

書き込まれたXMLファイルの内容は次のようになります。

XmlArrayItemAttributeを使用する方法

実はもう一つ方法があります。それは、ArrayListのメンバにXmlArrayItem属性を指定する方法です。この方法はSampleClassクラスに手を加えるだけで、あとは「クラス、配列などの内容をXMLファイルに保存、復元する」方法とまったく同じやり方で保存、復元できます。

この方法でSampleClassクラスを修正すると、次のようになります。(SampleClass2とMainClassクラスの内容は、一番はじめのコードと同じです。)

[VB.NET]
'XMLファイルに保存するオブジェクトのためのクラス
Public Class SampleClass
    '配列で配置できる型を指定する
    <System.Xml.Serialization.XmlArrayItem(GetType(SampleClass2))> _
    Public ClassList As New ArrayList

    Public Sub New()
        'ArrayListにSampleClass2オブジェクトを追加する
        Dim myClass2 As New SampleClass2
        myClass2.Number = 1
        myClass2.Message = "string"
        ClassList.Add(myClass2)
    End Sub
End Class
[C#]
//XMLファイルに保存するオブジェクトのためのクラス
public class SampleClass
{
    //配列で配置できる型を指定する
    [System.Xml.Serialization.XmlArrayItem(typeof(SampleClass2))]
    public ArrayList ClassList = new ArrayList();
    public SampleClass()
    {
        //ArrayListにSampleClass2オブジェクトを追加する
        SampleClass2 myClass2 = new SampleClass2();
        myClass2.Number = 1;
        myClass2.Message = "string";
        ClassList.Add(myClass2);
    }
}

この場合、書き込まれたXMLファイルの内容は次のようになります。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。