Étant donné le code XML suivant:
<?xml version="1.0"?>
<user_list>
<user>
<id>1</id>
<name>Joe</name>
</user>
<user>
<id>2</id>
<name>John</name>
</user>
</user_list>
Et la classe suivante:
public class User {
[XmlElement("id")]
public Int32 Id { get; set; }
[XmlElement("name")]
public String Name { get; set; }
}
Est-il possible d’utiliser XmlSerializer
pour désérialiser le code XML dans un fichier List<User>
? Si tel est le cas, quel type d'attributs supplémentaires dois-je utiliser ou quels paramètres supplémentaires dois-je utiliser pour construire l'instance XmlSerializer
?
Un tableau ( User[]
) serait acceptable, si un peu moins préférable.
Vous pouvez encapsuler la liste trivialement:
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);
}
}
Si vous décorez la classe User
avec le XmlType
pour qu'elle corresponde à la capitalisation requise:
[XmlType("user")]
public class User
{
...
}
Ensuite, le XmlRootAttribute
du XmlSerializer
ctor peut fournir la racine souhaitée et permettre une lecture directe dans 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);
}
Je pense avoir trouvé un meilleur moyen. Vous n'êtes pas obligé de mettre des attributs dans vos classes. J'ai mis au point deux méthodes de sérialisation et de désérialisation prenant la liste générique en paramètre.
Jetez un coup d'oeil (ça marche pour moi):
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;
}
Ainsi, vous pouvez sérialiser la liste que vous voulez! Vous n'avez pas besoin de spécifier le type de liste à chaque fois.
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);
Oui, il va sérialiser et désérialiser une liste <>. Assurez-vous simplement que vous utilisez l'attribut [XmlArray] en cas de doute.
[Serializable]
public class A
{
[XmlArray]
public List<string> strings;
}
Cela fonctionne à la fois avec Serialize () et Deserialize ().
Oui, il se désérialise en Liste <>. Pas besoin de le garder dans un tableau et de l'envelopper/de l'encapsuler dans une liste.
public class UserHolder
{
private List<User> users = null;
public UserHolder()
{
}
[XmlElement("user")]
public List<User> Users
{
get { return users; }
set { users = value; }
}
}
Code de désérialisation,
XmlSerializer xs = new XmlSerializer(typeof(UserHolder));
UserHolder uh = (UserHolder)xs.Deserialize(new StringReader(str));
Pas sûr de List <T> mais les tableaux sont certainement faisables. Et un peu de magie permet de retrouver facilement une liste.
public class UserHolder {
[XmlElement("list")]
public User[] Users { get; set; }
[XmlIgnore]
public List<User> UserList { get { return new List<User>(Users); } }
}
Que diriez-vous
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);
Pas particulièrement chic mais ça devrait marcher.