是否可以将 XML 反序列化为 List < T > ?

给定以下 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[])是可以接受的,如果不那么可取的话。

165582 次浏览

不确定 List < T > ,但是 Array 当然是可以做的。一点点魔法就能让你轻松再次进入名单。

public class UserHolder {
[XmlElement("list")]
public User[] Users { get; set; }


[XmlIgnore]
public List<User> UserList { get { return new List<User>(Users); } }
}

是的,它将序列化和反序列化 List < > 。

[Serializable]
public class A
{
[XmlArray]
public List<string> strings;
}

这同时适用于 Serialize ()和 Serialize ()。

你可以把这个列表简单地列出来:

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);
}
}

是的,它确实反序列化为 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));

我想我找到了一个更好的方法。您不必将属性放入类中。我制作了两个用于序列化和反序列化的方法,它们以泛型 list 作为参数。

看一下(对我来说很有效) :

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);

怎么样

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);

不是特别高级,但应该有用。

如果你用 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回答