Je sais qu'il est une vieille question, mais je suis tombé sur le même problème et aucune des solutions semble la question de adresse de l'OP.Voici donc ma solution (les commentaires sont en français si vous vous demandez):
#region Références
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
#endregion
namespace XmlSerializationTests
{
/// <summary>
/// Représente une liste qui peut être sérialisée en XML en tant que noeud racine.
/// </summary>
/// <typeparam name="T">Type des éléments de la liste.</typeparam>
public class XmlSerializableList<T>
: List<T>, IXmlSerializable
{
#region Variables
private static readonly XmlSerializer _ItemSerializer = new XmlSerializer(typeof(T));
private static readonly string _ItemName;
private string _RootName;
#endregion
#region Méthodes
/// <summary>
/// Initialisation statique
/// </summary>
static XmlSerializableList()
{
_ItemName = (typeof(T).GetCustomAttributes(typeof(XmlRootAttribute), true).FirstOrDefault() as XmlRootAttribute)?.ElementName ?? typeof(T).Name;
}
/// <summary>
/// Obtient le nom racine.
/// </summary>
protected virtual string RootName
{
get
{
if (string.IsNullOrWhiteSpace(_RootName)) _RootName = (GetType().GetCustomAttributes(typeof(XmlRootAttribute), true).FirstOrDefault() as XmlRootAttribute)?.ElementName ?? GetType().Name;
return _RootName;
}
}
/// <summary>
/// Obtient le nom des éléments.
/// </summary>
protected virtual string ItemName
{
get { return _ItemName; }
}
/// <summary>
/// Cette méthode est réservée et ne doit pas être utilisée.Lorsque vous implémentez l'interface IXmlSerializable, vous devez retourner la valeur null (Nothing dans Visual Basic) à partir cette méthode et, si la spécification d'un schéma personnalisé est requise, appliquez à la place <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"/> à la classe.
/// </summary>
/// <returns> <see cref="T:System.Xml.Schema.XmlSchema"/> qui décrit la représentation XML de l'objet qui est généré par la méthode <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/> et utilisé par la méthode <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/>.</returns>
public XmlSchema GetSchema()
{
return null;
}
/// <summary>
/// Génère un objet à partir de sa représentation XML.
/// </summary>
/// <param name="reader"><see cref="T:System.Xml.XmlReader"/> source à partir de laquelle l'objet est désérialisé.</param>
public void ReadXml(XmlReader reader)
{
if (!reader.IsEmptyElement)
{
reader.ReadStartElement();
while (reader.NodeType != XmlNodeType.EndElement)
{
T item = (T) _ItemSerializer.Deserialize(reader);
Add(item);
}
reader.ReadEndElement();
}
else reader.ReadStartElement();
}
/// <summary>
/// Convertit un objet en sa représentation XML.
/// </summary>
/// <param name="writer"><see cref="T:System.Xml.XmlWriter"/> flux dans lequel l'objet est sérialisé.</param>
public void WriteXml(XmlWriter writer)
{
foreach (var i in this)
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
_ItemSerializer.Serialize(writer, i, ns);
}
}
#endregion
}
}
Et ici une classe de test unitaire pour démontrer l'utilisation et les résultats:
#region Références
using System.IO;
using System.Text;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endregion
namespace XmlSerializationTests
{
[TestClass]
public class XmlSerializableListTests
{
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Birth { get; set; }
}
[XmlRoot("color")]
public class ColorDefinition
{
[XmlElement("name")] public string Name { get; set; }
[XmlElement("r")] public int Red { get; set; }
[XmlElement("g")] public int Green { get; set; }
[XmlElement("b")] public int Blue { get; set; }
}
public class Persons : XmlSerializableList<Person>
{
}
[XmlRoot("colors")]
public class ColorList : XmlSerializableList<ColorDefinition>
{
}
private T ReadXml<T>(string text) where T : class
{
XmlSerializer serializer = new XmlSerializer(typeof (T));
using (StringReader sr = new StringReader(text))
{
return serializer.Deserialize(sr) as T;
}
}
private string WriteXml<T>(T data) where T : class
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
serializer.Serialize(sw, data);
return sb.ToString();
}
}
[TestMethod]
public void ReadEmpty()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfInt32>
</XmlSerializableListOfInt32>";
XmlSerializableList<int> lst = ReadXml<XmlSerializableList<int>>(xml);
Assert.AreEqual(0, lst.Count);
}
[TestMethod]
public void ReadEmpty2()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfInt32 />";
XmlSerializableList<int> lst = ReadXml<XmlSerializableList<int>>(xml);
Assert.AreEqual(0, lst.Count);
}
[TestMethod]
public void ReadSimpleItems()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfInt32>
<int>0</int>
<int>52</int>
<int>79</int>
</XmlSerializableListOfInt32>";
XmlSerializableList<int> lst = ReadXml<XmlSerializableList<int>>(xml);
Assert.AreEqual(3, lst.Count);
Assert.AreEqual(0, lst[0]);
Assert.AreEqual(52, lst[1]);
Assert.AreEqual(79, lst[2]);
}
[TestMethod]
public void ReadComplexItems()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfPerson>
<Person>
<FirstName>Linus</FirstName>
<LastName>Torvalds</LastName>
<Birth>1969</Birth>
</Person>
<Person>
<FirstName>Bill</FirstName>
<LastName>Gates</LastName>
<Birth>1955</Birth>
</Person>
<Person>
<FirstName>Steve</FirstName>
<LastName>Jobs</LastName>
<Birth>1955</Birth>
</Person>
</XmlSerializableListOfPerson>";
XmlSerializableList<Person> lst = ReadXml<XmlSerializableList<Person>>(xml);
Assert.AreEqual(3, lst.Count);
Assert.AreEqual("Linus", lst[0].FirstName);
Assert.AreEqual("Torvalds", lst[0].LastName);
Assert.AreEqual(1969, lst[0].Birth);
Assert.AreEqual("Bill", lst[1].FirstName);
Assert.AreEqual("Gates", lst[1].LastName);
Assert.AreEqual(1955, lst[1].Birth);
Assert.AreEqual("Steve", lst[2].FirstName);
Assert.AreEqual("Jobs", lst[2].LastName);
Assert.AreEqual(1955, lst[2].Birth);
}
[TestMethod]
public void ReadInheritedPersons()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<Persons>
<Person>
<FirstName>Linus</FirstName>
<LastName>Torvalds</LastName>
<Birth>1969</Birth>
</Person>
<Person>
<FirstName>Bill</FirstName>
<LastName>Gates</LastName>
<Birth>1955</Birth>
</Person>
<Person>
<FirstName>Steve</FirstName>
<LastName>Jobs</LastName>
<Birth>1955</Birth>
</Person>
</Persons>";
Persons lst = ReadXml<Persons>(xml);
Assert.AreEqual(3, lst.Count);
Assert.AreEqual("Linus", lst[0].FirstName);
Assert.AreEqual("Torvalds", lst[0].LastName);
Assert.AreEqual(1969, lst[0].Birth);
Assert.AreEqual("Bill", lst[1].FirstName);
Assert.AreEqual("Gates", lst[1].LastName);
Assert.AreEqual(1955, lst[1].Birth);
Assert.AreEqual("Steve", lst[2].FirstName);
Assert.AreEqual("Jobs", lst[2].LastName);
Assert.AreEqual(1955, lst[2].Birth);
}
[TestMethod]
public void ReadInheritedColors()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<colors>
<color>
<name>red</name>
<r>255</r>
<g>0</g>
<b>0</b>
</color>
<color>
<name>green</name>
<r>0</r>
<g>255</g>
<b>0</b>
</color>
<color>
<name>yellow</name>
<r>255</r>
<g>255</g>
<b>0</b>
</color>
</colors>";
ColorList lst = ReadXml<ColorList>(xml);
Assert.AreEqual(3, lst.Count);
Assert.AreEqual("red", lst[0].Name);
Assert.AreEqual(255, lst[0].Red);
Assert.AreEqual(0, lst[0].Green);
Assert.AreEqual(0, lst[0].Blue);
Assert.AreEqual("green", lst[1].Name);
Assert.AreEqual(0, lst[1].Red);
Assert.AreEqual(255, lst[1].Green);
Assert.AreEqual(0, lst[1].Blue);
Assert.AreEqual("yellow", lst[2].Name);
Assert.AreEqual(255, lst[2].Red);
Assert.AreEqual(255, lst[2].Green);
Assert.AreEqual(0, lst[2].Blue);
}
[TestMethod]
public void WriteEmpty()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfInt32 />";
XmlSerializableList<int> lst = new XmlSerializableList<int>();
string result = WriteXml(lst);
Assert.AreEqual(xml, result);
}
[TestMethod]
public void WriteSimpleItems()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfInt32>
<int>0</int>
<int>52</int>
<int>79</int>
</XmlSerializableListOfInt32>";
XmlSerializableList<int> lst = new XmlSerializableList<int>() {0, 52, 79};
string result = WriteXml(lst);
Assert.AreEqual(xml, result);
}
[TestMethod]
public void WriteComplexItems()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<XmlSerializableListOfPerson>
<Person>
<FirstName>Linus</FirstName>
<LastName>Torvalds</LastName>
<Birth>1969</Birth>
</Person>
<Person>
<FirstName>Bill</FirstName>
<LastName>Gates</LastName>
<Birth>1955</Birth>
</Person>
<Person>
<FirstName>Steve</FirstName>
<LastName>Jobs</LastName>
<Birth>1955</Birth>
</Person>
</XmlSerializableListOfPerson>";
XmlSerializableList<Person> persons = new XmlSerializableList<Person>
{
new Person {FirstName = "Linus", LastName = "Torvalds", Birth = 1969},
new Person {FirstName = "Bill", LastName = "Gates", Birth = 1955},
new Person {FirstName = "Steve", LastName = "Jobs", Birth = 1955}
};
string result = WriteXml(persons);
Assert.AreEqual(xml, result);
}
[TestMethod]
public void WriteInheritedPersons()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<Persons>
<Person>
<FirstName>Linus</FirstName>
<LastName>Torvalds</LastName>
<Birth>1969</Birth>
</Person>
<Person>
<FirstName>Bill</FirstName>
<LastName>Gates</LastName>
<Birth>1955</Birth>
</Person>
<Person>
<FirstName>Steve</FirstName>
<LastName>Jobs</LastName>
<Birth>1955</Birth>
</Person>
</Persons>";
Persons lst = new Persons
{
new Person {FirstName = "Linus", LastName = "Torvalds", Birth = 1969},
new Person {FirstName = "Bill", LastName = "Gates", Birth = 1955},
new Person {FirstName = "Steve", LastName = "Jobs", Birth = 1955}
};
string result = WriteXml(lst);
Assert.AreEqual(xml, result);
}
[TestMethod]
public void WriteInheritedColors()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<colors>
<color>
<name>red</name>
<r>255</r>
<g>0</g>
<b>0</b>
</color>
<color>
<name>green</name>
<r>0</r>
<g>255</g>
<b>0</b>
</color>
<color>
<name>yellow</name>
<r>255</r>
<g>255</g>
<b>0</b>
</color>
</colors>";
ColorList lst = new ColorList
{
new ColorDefinition { Name = "red", Red = 255, Green = 0, Blue = 0 },
new ColorDefinition { Name = "green", Red = 0, Green = 255, Blue = 0 },
new ColorDefinition { Name = "yellow", Red = 255, Green = 255, Blue = 0 }
};
string result = WriteXml(lst);
Assert.AreEqual(xml, result);
}
}
}
tribe84 a posté réponse ... – lanicor
Ma question était que le tableau était marqué en interne – Nick