DOBON.NET DOBON.NETプログラミング掲示板過去ログ

自作コレクションの入っているArrayListのシリアル化

環境/言語:[windows7 VisualC#.NET2010 Framework4]
分類:[.NET]

こんにちは。
ほとんど初心者で恐縮ですが、よろしくおねがいします。

私は、ある設定をユーザーごとに管理使用と思っていて、次のようなクラスを作りました。
public class an_set
{
public string _CtrName;
public object _Property;
public Type _CtrType;

public string CtrName
{
get { return _CtrName; }
set { _CtrName = value; }
}
public object Property
{
get { return _Property; }
set { _Property = value; }
}
public Type CtrType
{
get { return _CtrType; }
set { _CtrType = value; }

}
}
public class NArray : ArrayList
{
public string _TaskName;

public string TaskName
{
get { return _TaskName; }
set { _TaskName = value; }
}

}
NArrayにはan_setがたくさん収納されており、別のArrayListにそのようなNArrayをたくさん収納されています。
これを、
//XmlSerializerオブジェクトを作成
//書き込むオブジェクトの型を指定する
System.Xml.Serialization.XmlSerializer serializer1 = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), new Type[] { typeof(an_set), typeof(NArray), typeof(string) });
//ファイルを開く
System.IO.FileStream fs1 = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
//シリアル化し、XMLファイルに保存する
serializer1.Serialize(fs1, SetCol);
//閉じる
fs1.Close();
でシリアル化し、
//XmlSerializerオブジェクトの作成NArray settings = Search_Settings(SetCol, (string)listBox1.SelectedItem);
System.Xml.Serialization.XmlSerializer serializer2 = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), new Type[] { typeof(an_set), typeof(NArray),typeof(string) });
//ファイルを開く
System.IO.FileStream fs2 = new System.IO.FileStream(fileName, System.IO.FileMode.Open);
//XMLファイルから読み込み、逆シリアル化する
SetCol = (ArrayList)serializer2.Deserialize(fs2);
//閉じる
fs2.Close();
で逆シリアル化して元のArrayListを取り出そうと思っているのですが、
いざ取り出してみるとNArrayのTaskNameプロパティが全てNullになってしまいます。
なんでだろうと思って、シリアル化した後のXMLファイルを見てみると、NArrayのTaskNameプロパティにあたる部分が全く見あたりませんでした。

どうしてこのようになってしまうのでしょうか?
また、解決策はあるでしょうか?
どうか、ご教授よろしくお願い致します。
XmlSerializer の仕様ですね。IEnumerable または ICollection 実装クラスは特殊なシリアライズを行います(具体的な処理は MSDN で XmlSerializer の解説中の [メモ] をお読み下さい)。
ArrayList もその派生クラスも当然 ICollection を実装しているので、その特殊なシリアライズが行われることになります。

解決法としては、直接コレクションが名前をも持つのではなく、Task かなんかというクラスを用意し、それに string 型の Name プロパティと List<an_set> 型の Items プロパティを持たせる(名前は適当です)、という形にするのが一般的かと思います。

それから、
・.NET 2.0 以降なら ArrayList ではなく List<T> を使った方が(シリアライズ以外の場面で)楽です。
・プロパティを公開してるんだったらフィールドの方は private でいいでしょう。
Hongliang様
> 解決法としては、直接コレクションが名前をも持つのではなく、Task かなんかというクラスを用意し、それに string 型の Name プロパティと List<an_set> 型の Items プロパティを持たせる(名前は適当です)、という形にするのが一般的かと思います。
>
> それから、
> ・.NET 2.0 以降なら ArrayList ではなく List<T> を使った方が(シリアライズ以外の場面で)楽です。
> ・プロパティを公開してるんだったらフィールドの方は private でいいでしょう。
見事に解決いたしました。
public class Task
{
private string _TaskName;
public List<an_set> sets;
public string TaskName
{
get { return _TaskName; }
set { _TaskName = value; }
}

}
とすることによって、ちゃんとシリアル化され、読み出すこともできるようになりました。
動的にサイズが変化する配列というと今まで「ArrayList」しかしらなかったです(汗
List<T>なんてのもあるのですね。もっとよく勉強していきたいと思います。
本当にありがとうございました!
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板