XMLファイルにシリアル化するクラスのコレクションがあります。次のようになります。
public class Foo
{
public List<Bar> BarList { get; set; }
}
次のように、バーはプロパティのコレクションの単なるラッパーです。
public class Bar
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
これをマークアップして、XMLファイルに出力するようにします。これは、永続化と、XSLTを介してNice可読形式に設定をレンダリングするために使用されます。
このような素敵なXML表現を取得したいです。
<?xml version="1.0" encoding="utf-8"?>
<Foo>
<BarList>
<Bar>
<Property1>Value</Property1>
<Property2>Value</Property2>
</Bar>
<Bar>
<Property1>Value</Property1>
<Property2>Value</Property2>
</Bar>
</Barlist>
</Foo>
barlist内のすべてのBarは、すべてのプロパティとともに書き込まれます。クラス定義を機能させるには、クラス定義にマークアップが必要になると確信していますが、適切な組み合わせが見つからないようです。
Fooを属性でマークしました
[XmlRoot("Foo")]
そしてその list<Bar>
属性付き
[XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName="Bar")]
シリアライザに私が何をしたいのかを伝えようとしました。ただし、これは機能していないようで、次のように空のタグを取得します。
<?xml version="1.0" encoding="utf-8"?>
<Foo>
<Barlist />
</Foo>
自動プロパティを使用しているという事実が何らかの効果をもたらすかどうか、またはジェネリックの使用に特別な処理が必要かどうかはわかりません。文字列のリストのような単純な型で動作するようになりましたが、これまでのところクラスのリストは私を避けています。
確認するために、Barを[Serializable]としてマークしましたか?
また、逆シリアル化するには、Barにパラメーターなしのctorが必要です
うーん、私は使用しました:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Foo f = new Foo();
f.BarList = new List<Bar>();
f.BarList.Add(new Bar { Property1 = "abc", Property2 = "def" });
XmlSerializer ser = new XmlSerializer(typeof(Foo));
using (FileStream fs = new FileStream(@"c:\sertest.xml", FileMode.Create))
{
ser.Serialize(fs, f);
}
}
}
public class Foo
{
[XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName = "Bar")]
public List<Bar> BarList { get; set; }
}
[XmlRoot("Foo")]
public class Bar
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
そしてそれは生産した:
<?xml version="1.0"?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BarList>
<Bar>
<Property1>abc</Property1>
<Property2>def</Property2>
</Bar>
</BarList>
</Foo>
すべてが素晴らしく見えます。 @Carlが言ったように、クラスに[Serializable]属性を追加する必要がありますが、それ以外はXMLの作成が機能するはずです。
Foo
[Serializable]
[XmlRoot("Foo")]
public class Foo
{
[XmlArray("BarList"), XmlArrayItem(typeof(Bar), ElementName = "Bar")]
public List<Bar> BarList { get; set; }
}
バー
[Serializable]
public class Bar
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
テストするコード
Foo f = new Foo();
f.BarList = new List<Bar>();
f.BarList.Add(new Bar() { Property1 = "s", Property2 = "2" });
f.BarList.Add(new Bar() { Property1 = "s", Property2 = "2" });
FileStream fs = new FileStream("c:\\test.xml", FileMode.OpenOrCreate);
System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(Foo));
s.Serialize(fs, f);
出力
<?xml version="1.0" ?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BarList>
<Bar>
<Property1>s</Property1>
<Property2>2</Property2>
</Bar>
<Bar>
<Property1>s</Property1>
<Property2>2</Property2>
</Bar>
</BarList>
</Foo>
var xmlfromLINQ = new XElement("BarList",
from c in BarList
select new XElement("Bar",
new XElement("Property1", c.Property1),
new XElement("Property2", c.Property2)
));
このアイテムが投稿されてから5年以上が経過しています。 2013年7月(.NET Framework 4.5)からの経験を提供します。価値があり、誰に関心があるかについて:
クラスを次のように定義すると:(VB.Net code)
<Serializable> Public Class MyClass
Public Property Children as List(of ChildCLass)
<XmlAttribute> Public Property MyFirstProperty as string
<XmlAttribute> Public Property MySecondProperty as string
End Class
<Serializable> Public Class ChildClass
<XmlAttribute> Public Property MyFirstProperty as string
<XmlAttribute> Public Property MySecondProperty as string
End Class
この定義により、クラスは問題なく(デ)シリアル化されます。これは、ここから出てくるXMLです。
<MyClass> MyFirstProperty="" MySecondProperty=""
<Children>
<ChildClass> MyFirstProperty="" MySecondProperty=""
</ChildClass>
</Children>
</MyClass>
解決策がList(of T)要素の<XmlElement>
プレフィックスを省くことであると理解するのにたった2日しかかかりませんでした。