[英]How to use XmlInclude to serialize IEnumerable
使用XmlSerializer
序列化IEnumerable
時遇到了問題。 由於IEnumerable
表示object
列表,因此XmlSerializer
不知道需要序列化什么類型。 但是因為需要知道,所以在遇到object
以外的其他類型時會拋出InvalidOperationException
。
類型Foo.Bar不可預期。 使用XmlInclude或SoapInclude屬性可以指定靜態未知的類型。
XmlIncludeAttribute
旨在應用於一種方法,以指示返回值可以是某種類型。 但是, IEnumerable
沒有可以將屬性放在上面的方法。
我嘗試將它們應用於GetEnumerator
:
public class Bar : IEnumerable
{
private List<object> list;
public Bar()
{
}
[XmlInclude(typeof(Bar))]
[XmlInclude(typeof(ChildBar))]
public IEnumerator GetEnumerator()
{
return list.GetEnumerator();
}
public void Add(Bar bar)
{
list.Add(bar);
}
public void Add(ChildBar childBar)
{
list.Add(childBar);
}
// used for deserialization
public void Add(object o)
{
if (o is Bar || o is ChildBar)
{
list.Add(o);
}
}
// more irrelevant stuff
}
public class ChildBar
{
public ChildBar()
{
}
// more irrelevant stuff
}
那並不能解決問題,我也不知道該在哪里使用這些屬性。
我應該放在哪里? 沒有他們,我可以解決它嗎? 我可以避免編寫自己的枚舉器嗎?
編輯:由於它們是我先前的回答的幾個缺陷-沒有包含更多條的條並且不使用xmlAttributes,這是我的新解決方案:但是,這沒有實現...
編輯:好吧,我回去回顧了一些事情,這是實現ICollection的最終解決方案,希望這對嘗試找到序列化Collections的解決方案的所有人有所幫助。
public class Program
{
static void Main(string[] args)
{
var program = new Program();
program.SerializeObject();
}
private int tierIndex = 1;
public void SerializeObject()
{
var barCollection = new BarCollection();
var bar1 = new Bar() { Name = "bar1" };
barCollection.Add(bar1);
var bar2 = new Bar() { Name = "bar2" };
barCollection.Add(bar2);
var bar3 = new Bar() { Name = "bar3" };
bar2.BarCollection.Add(bar3);
var bar4 = new Bar() { Name = "bar4" };
bar2.BarCollection.Add(bar4);
var bar5 = new Bar() { Name = "bar 5" };
barCollection.Add(bar5);
var bar6 = new Bar() { Name = "bar 6" };
barCollection.Add(bar6);
var bar7 = new Bar() { Name = "bar 7" };
bar6.BarCollection.Add(bar7);
var bar8 = new Bar() { Name = "bar 8" };
bar7.BarCollection.Add(bar8);
var x = new XmlSerializer(typeof(BarCollection));
x.Serialize(Console.Out, barCollection);
Console.WriteLine("\n");
WriteCollection(barCollection);
Console.ReadLine();
}
public void WriteCollection(BarCollection barCollection)
{
tierIndex++;
foreach (Bar bar in barCollection)
{
Console.Write(new StringBuilder().Insert(0, "--", tierIndex) + "> ");
Console.Write(bar.Name + "\n");
WriteCollection(bar.BarCollection);
}
tierIndex--;
}
}
public class BarCollection : ICollection
{
private readonly ArrayList barNodes = new ArrayList();
public Bar this[int index]
{
get { return (Bar) barNodes[index]; }
}
public void CopyTo(Array a, int index)
{
barNodes.CopyTo(a, index);
}
public int Count
{
get { return barNodes.Count; }
}
public object SyncRoot
{
get { return this; }
}
public bool IsSynchronized
{
get { return false; }
}
public IEnumerator GetEnumerator()
{
return barNodes.GetEnumerator();
}
public void Add(Bar bar)
{
barNodes.Add(bar);
}
public void Add(Object bar)
{
barNodes.Add((Bar) bar);
}
}
public class Bar
{
[XmlAttribute(AttributeName = "Name")]
public string Name;
[XmlArray(ElementName = "BarNodes", IsNullable = true)]
public BarCollection BarCollection = new BarCollection();
}
繼承人的輸出:
<?xml version="1.0" encoding="IBM437"?>
<ArrayOfBar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Bar Name="bar1">
<BarNodes />
</Bar>
<Bar Name="bar2">
<BarNodes>
<Bar Name="bar3">
<BarNodes />
</Bar>
<Bar Name="bar4">
<BarNodes />
</Bar>
</BarNodes>
</Bar>
<Bar Name="bar 5">
<BarNodes />
</Bar>
<Bar Name="bar 6">
<BarNodes>
<Bar Name="bar 7">
<BarNodes>
<Bar Name="bar 8">
<BarNodes />
</Bar>
</BarNodes>
</Bar>
</BarNodes>
</Bar>
</ArrayOfBar>
----> bar1
----> bar2
------> bar3
------> bar4
----> bar 5
----> bar 6
------> bar 7
--------> bar 8
另一個堆棧參考: XmlSerializer不會序列化IEnumerable
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.