是否可以将 XML 反序列化为 List<T>?
Posted
技术标签:
【中文标题】是否可以将 XML 反序列化为 List<T>?【英文标题】:Is it possible to deserialize XML into List<T>? 【发布时间】:2010-10-11 02:56:09 【问题描述】:给定以下 XML:
<?xml version="1.0"?>
<user_list>
<user>
<id>1</id>
<name>Joe</name>
</user>
<user>
<id>2</id>
<name>John</name>
</user>
</user_list>
还有以下类:
public class User
[XmlElement("id")]
public Int32 Id get; set;
[XmlElement("name")]
public String Name get; set;
是否可以使用 XmlSerializer
将 xml 反序列化为 List<User>
?如果是这样,我需要使用什么类型的附加属性,或者我需要使用什么附加参数来构造XmlSerializer
实例?
数组 (User[]
) 是可以接受的,如果不太可取的话。
【问题讨论】:
【参考方案1】:不确定 List
public class UserHolder
[XmlElement("list")]
public User[] Users get; set;
[XmlIgnore]
public List<User> UserList get return new List<User>(Users);
【讨论】:
可以不用“holder”类吗? @Daniel,AFAIK,没有。您需要序列化和反序列化为一些具体的对象类型。我不相信 XML 序列化本身支持集合类作为序列化的开始。不过,我不是 100% 知道这一点。 [XmlElement("list")] 应该是 [XmlArray("list")] 代替。这是反序列化在 .NET 4.5 中为我工作的唯一方法【参考方案2】:是的,它会序列化和反序列化一个 List。如有疑问,请确保使用 [XmlArray] 属性。
[Serializable]
public class A
[XmlArray]
public List<string> strings;
这适用于 Serialize() 和 Deserialize()。
【讨论】:
【参考方案3】:您可以简单地封装列表:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlRoot("user_list")]
public class UserList
public UserList() Items = new List<User>();
[XmlElement("user")]
public List<User> Items get;set;
public class User
[XmlElement("id")]
public Int32 Id get; set;
[XmlElement("name")]
public String Name get; set;
static class Program
static void Main()
XmlSerializer ser= new XmlSerializer(typeof(UserList));
UserList list = new UserList();
list.Items.Add(new User Id = 1, Name = "abc");
list.Items.Add(new User Id = 2, Name = "def");
list.Items.Add(new User Id = 3, Name = "ghi");
ser.Serialize(Console.Out, list);
【讨论】:
使用 [XmlElement("user")] 的很好的解决方案可以避免额外级别的元素。看着这个,我确信它会发出一个.Items
成员执行此操作。【参考方案4】:
是的,它确实反序列化为 List。无需将其保存在数组中并将其包装/封装在列表中。
public class UserHolder
private List<User> users = null;
public UserHolder()
[XmlElement("user")]
public List<User> Users
get return users;
set users = value;
反序列化代码,
XmlSerializer xs = new XmlSerializer(typeof(UserHolder));
UserHolder uh = (UserHolder)xs.Deserialize(new StringReader(str));
【讨论】:
【参考方案5】:我想我找到了更好的方法。您不必将属性放入您的类中。我做了两种以泛型列表为参数的序列化和反序列化方法。
看看(对我有用):
private void SerializeParams<T>(XDocument doc, List<T> paramList)
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(paramList.GetType());
System.Xml.XmlWriter writer = doc.CreateWriter();
serializer.Serialize(writer, paramList);
writer.Close();
private List<T> DeserializeParams<T>(XDocument doc)
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(List<T>));
System.Xml.XmlReader reader = doc.CreateReader();
List<T> result = (List<T>)serializer.Deserialize(reader);
reader.Close();
return result;
所以你可以序列化任何你想要的列表!不需要每次都指定列表类型。
List<AssemblyBO> list = new List<AssemblyBO>();
list.Add(new AssemblyBO());
list.Add(new AssemblyBO() DisplayName = "Try", Identifier = "243242" );
XDocument doc = new XDocument();
SerializeParams<T>(doc, list);
List<AssemblyBO> newList = DeserializeParams<AssemblyBO>(doc);
【讨论】:
感谢您实际回答问题。我要补充一点,对于List<MyClass>
,文档元素应命名为ArrayOfMyClass
。【参考方案6】:
怎么样
XmlSerializer xs = new XmlSerializer(typeof(user[]));
using (Stream ins = File.Open(@"c:\some.xml", FileMode.Open))
foreach (user o in (user[])xs.Deserialize(ins))
userList.Add(o);
不是特别花哨,但应该可以。
【讨论】:
欢迎来到***!最好为示例代码提供简短描述以提高发布准确性:)【参考方案7】:如果您使用XmlType
装饰User
类以匹配所需的大小写:
[XmlType("user")]
public class User
...
然后XmlSerializer
ctor 上的XmlRootAttribute
可以提供所需的根并允许直接读入 List:
// e.g. my test to create a file
using (var writer = new FileStream("users.xml", FileMode.Create))
XmlSerializer ser = new XmlSerializer(typeof(List<User>),
new XmlRootAttribute("user_list"));
List<User> list = new List<User>();
list.Add(new User Id = 1, Name = "Joe" );
list.Add(new User Id = 2, Name = "John" );
list.Add(new User Id = 3, Name = "June" );
ser.Serialize(writer, list);
...
// read file
List<User> users;
using (var reader = new StreamReader("users.xml"))
XmlSerializer deserializer = new XmlSerializer(typeof(List<User>),
new XmlRootAttribute("user_list"));
users = (List<User>)deserializer.Deserialize(reader);
信用:基于来自YK1的answer。
【讨论】:
在我看来,这显然是问题的答案。问题是关于反序列化为 ListXmlSerializer
必须被静态缓存和重用以避免严重的内存泄漏,详情请参阅Memory Leak using StreamReader and XmlSerializer。以上是关于是否可以将 XML 反序列化为 List<T>?的主要内容,如果未能解决你的问题,请参考以下文章