C#・VB.Netでプログラムを書くときに、いつもお世話になっているdobonにObject配列やArrayListをXMLシリアル化するにObject配列やArrayListについては書かれているのですが、ジェネリックリストの場合はどうなるのかと試してみたら、特に何も考えなくても動くようでした(ジェネリックリストの場合はメンバの型が決まっているからでしょうか)。
ただ、シリアル化したいオブジェクトに引数がないコンストラクタが無いとエラー(例外:InvaridOperationException)になります。
お恥ずかしい話しですが、私は今までアクションの下にある「詳細の表示」を押せば例外の詳細を表示できることを知らなかったため、原因(引数がないコンストラクタが必要)に気づくまで時間がかかってしまいました_| ̄|○
「詳細の表示」を押すと
こんな感じで「パラメータを持たないコンストラクタが含まれていないため、これをシリアル化することはできません。」とちゃんと書いてありました。
シリアル化・逆シリアル化するときに、内部で引数を持たないコンストラクタを呼び出して、インスタンスにプロパティ等のデータを持たせているようなので、このようなエラーが起きてしまうようです。
ということでサンプルソースを貼り付けておきます。
まずはシリアル化したいクラスの定義から。
今回シリアル化したい会社(clsCompany)クラスは、創立年(Establish)と社長(President)、従業員(Employees)から成り、社長はclsPerson型、従業員はclsPerson型のジェネリックリスト(List
public class clsCompany { private int _establish; private clsPerson _president; private List<clsPerson> _employees; public int Establish { get { return _establish; } set { _establish = value; } } public clsPerson President { get { return _president; } set { _president = value; } } public List<clsPerson> Employees { get { return _employees; } set { _employees = value; } } public clsCompany(clsPerson president, int establish) { this._president = president; this._establish = establish; this._employees = new List<clsPerson>(); } //引数が空のコンストラクタ…下の行のコメントを外さないとエラーになる //public clsCompany() { } } public class clsPerson { private string _name; private int _age; public string Name { get { return _name; } set { _name = value; } } public int Age { get { return _age; } set { _age = value; } } //コンストラクタ public clsPerson(string name, int age) { this._name = name; this._age = age; } //引数が空のコンストラクタ public clsPerson() { } }
ここで重要なのは19行目と36行目に書いた引数を持たないコンストラクタです。
このサンプルでは19行目をコメントアウトしているので、前述のエラーが発生します。
んで、インスタンス発生→シリアル化はこちら
//社長誕生 clsPerson president = new clsPerson("佐藤 太郎", 55); //会社創立 clsCompany comp = new clsCompany(president, 2015); //社員入社 comp.Employees.Add(new clsPerson("鈴木 一郎", 22)); comp.Employees.Add(new clsPerson("高橋 二郎", 23)); comp.Employees.Add(new clsPerson("田中 三郎", 24)); //ここからシリアル化 XmlSerializer serializer = new XmlSerializer(typeof(clsCompany)); using (StreamWriter sw = new StreamWriter("comp.xml", false, Encoding.UTF8)) { serializer.Serialize(sw, comp); }
10行目まではシリアル化したいclsCompany型のインスタンス「comp」を整えているところです。
実際のシリアル化は、13~17行目です。
13行目でclsCompany型をシリアライズするXmlSerializerクラス(インスタンスはserializer)を発生させています。
14行目で書き込みに使用するStreamWriterを発生させています。
16行目でStreamWriterのインスタンスswとシリアライズしたいインスタンス「comp」を引数として、実際のシリアライズを行っています。
なお、サンプルはソースファイルの冒頭に
using System.IO; using System.Xml.Serialization;
が書かれている事が前提になっていますのでご注意ください。
ちなみに、出来たXMLはこんな感じになっています。
<?xml version="1.0" encoding="utf-8"?> <clsCompany xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Establish>2015</Establish> <President> <Name>佐藤 太郎</Name> <Age>55</Age> </President> <Employees> <clsPerson> <Name>鈴木 一郎</Name> <Age>22</Age> </clsPerson> <clsPerson> <Name>高橋 二郎</Name> <Age>23</Age> </clsPerson> <clsPerson> <Name>田中 三郎</Name> <Age>24</Age> </clsPerson> </Employees> </clsCompany>
参考
・【C#】オブジェクトのシリアル化 ジェネリックリストもOK!
・ClassのメンバのListはシリアライズされない?