【发布时间】:2009-09-25 14:12:51
【问题描述】:
好的,到此为止。
我已经可以使用XmlSerializer 反序列化单个对象,但是反序列化列表被证明是一个真正令人头疼的问题。我首先尝试序列化List<Foo>,并且序列化程序在根<ArrayOfFoo> 元素内序列化多个<Foo> XML 结构。事实证明,反序列化是有问题的,所以看起来我需要自己定义 'ArrayOfFoo' 元素。所以,我有一个类在工作,它是列表的“包装器”,如以下程序所示:
using System;
using System.IO;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace XmlTester2
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("XML tester...");
string xml =
"<ItemList xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<Person i:type=\"PersonI2\">" + "<Field1>field1Val</Field1>" +
"<Field2>field2Val</Field2>" + "<Field3>field3Val</Field3>" +
"<Field4>field4Val</Field4>" + "</Person>" +
"<Account i:type=\"AccountI2\">" + "<Field1>field1Val</Field1>" +
"<Field2>field2Val</Field2>" + "<Field3>field3Val</Field3>" +
"<Field4>field4Val</Field4>" + "</Account>" +
"<Person i:type=\"PersonI2\">" + "<Field1>field1Val</Field1>" +
"<Field2>field2Val</Field2>" + "<Field3>field3Val</Field3>" +
"<Field4>field4Val</Field4>" + "</Person>" + "</ItemList>";
XmlSerializer ser = new XmlSerializer(typeof(ItemList));
using (var reader = new StringReader(xml))
{
ItemList result = (ItemList)ser.Deserialize(reader);
}
Console.WriteLine("Break here and check 'result' in Quickwatch...");
Console.ReadKey();
}
}
[XmlRootAttribute(IsNullable = false)]
public class ItemList
{
[XmlElementAttribute("Person")]
public List<Person> Persons { get; set; }
[XmlElementAttribute("Account")]
public List<Account> Accounts { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "Person", Namespace = "")]
[XmlInclude(typeof(PersonI2))]
public class Person
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "PersonI2", Namespace = "")]
public class PersonI2 : Person
{
public string Field4 { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "Account", Namespace = "")]
[XmlInclude(typeof(AccountI2))]
public class Account
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "AccountI2", Namespace = "")]
public class AccountI2 : Account
{
public string Field4 { get; set; }
}
}
但是,这个“包装器”ItemList 仍然必须在其中手动定义所有可能包含的元素(在示例中,Person 和 Account)。真正理想的是拥有一个通用的列表包装类。我知道这有点希望,但有办法做到这一点吗?我正在考虑这些方面的东西(这不起作用,只是为了给你一个大致的想法):
using System;
using System.IO;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace XmlTester3
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("XML tester...");
string xml =
"<ItemList xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<Person i:type=\"PersonI2\">" +
"<Field1>field1Val</Field1>" +
"<Field2>field2Val</Field2>" +
"<Field3>field3Val</Field3>" +
"<Field4>field4Val</Field4>" +
"</Person>" +
"<Person i:type=\"PersonI2\">" +
"<Field1>field1Val</Field1>" +
"<Field2>field2Val</Field2>" +
"<Field3>field3Val</Field3>" +
"<Field4>field4Val</Field4>" +
"</Person>" +
"</ItemList>";
XmlSerializer ser = new XmlSerializer(typeof(ItemList<Person>));
using (var reader = new StringReader(xml))
{
ItemList<Person> result = (ItemList<Person>)ser.Deserialize(reader);
}
Console.WriteLine("Break here and check 'result' in Quickwatch...");
Console.ReadKey();
}
}
[XmlRootAttribute(IsNullable = false)]
[XmlInclude(typeof(Person))]
[XmlInclude(typeof(PersonI2))]
[XmlInclude(typeof(Account))]
[XmlInclude(typeof(AccountI2))]
public class ItemList<T>
{
[XmlElementAttribute]
public List<T> Items { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "Person", Namespace = "")]
[XmlInclude(typeof(PersonI2))]
public class Person
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "PersonI2", Namespace = "")]
public class PersonI2 : Person
{
public string Field4 { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "Account", Namespace = "")]
[XmlInclude(typeof(AccountI2))]
public class Account
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
[XmlTypeAttribute(AnonymousType = false, TypeName = "AccountI2", Namespace = "")]
public class AccountI2 : Account
{
public string Field4 { get; set; }
}
}
因此,在 ItemList 中传递的 XML 结构只能是一种类型,例如本例中的 Person,我可以定义一个 ItemList<Person>,它允许我反序列化包含多个人对象?有任何想法吗?如有必要,我不介意为ItemList 可能包含的每种类型都使用[XmlInclude...] 标记ItemList 类。
我猜这是可能的,我只是还没弄清楚怎么做? :-) 还是默认的 XmlSerializer 太挑剔了?
【问题讨论】:
-
从 ArrayOfFoo 元素反序列化到 List
应该可以工作(我只是在一个基本的测试应用程序中做到了) - 有什么问题?
标签: c# serialization xml-serialization