[xml] serialiser un dictionary générique

Contenu du snippet

Voici comment sérialiser et déserialiser simplement un dictionnaire.
Le code fonctionne avec n'importe quel type, à condition qu'il soit sérialisable (et donc qu'il ait un constructeur sans paramètre, mais qui peut être private).

Source / Exemple :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Xml;

public static class DictionarySerializer<TKey, TValue>
	where TKey : class 
	where TValue : class
{
	private const string NODE_ROOT = "root";
	private const string NODE_ITEM = "item";
	private const string NODE_KEY = "key";
	private const string NODE_VALUE = "value";

	public static string ObjectToXml(Dictionary<TKey, TValue> dic)
	{
		string xml = "";
		try
		{
			StringBuilder output = new StringBuilder();

			XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
			xmlWriterSettings.Encoding = new UTF8Encoding(false);
			xmlWriterSettings.Indent = true;
			XmlWriter writer = XmlWriter.Create(output, xmlWriterSettings);

			XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
			XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

			writer.WriteStartDocument();
			writer.WriteStartElement(NODE_ROOT);
			foreach (TKey key in dic.Keys)
			{
				writer.WriteStartElement(NODE_ITEM);
				writer.WriteStartElement(NODE_KEY);
				keySerializer.Serialize(writer, key);
				writer.WriteEndElement();

				writer.WriteStartElement(NODE_VALUE);
				TValue value = dic[key];
				valueSerializer.Serialize(writer, value);
				writer.WriteEndElement();

				writer.WriteEndElement();
			}
			writer.WriteEndDocument();
			writer.Flush();
			xml = output.ToString();
		}
		catch (Exception ex)
		{
			// Log error...
		}
		return xml;
	}

	public static Dictionary<TKey, TValue> XmlToObject(string _xml)
	{
		Dictionary<TKey, TValue> ret = new Dictionary<TKey, TValue>();
		try
		{
			XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
			XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

			using (XmlReader reader = XmlReader.Create(new StringReader(_xml)))
			{
				reader.Read();
				reader.ReadStartElement(NODE_ROOT);

				while (reader.NodeType != XmlNodeType.EndElement)
				{
					reader.ReadStartElement(NODE_ITEM);

					reader.ReadStartElement(NODE_KEY);
					TKey key = (TKey)keySerializer.Deserialize(reader);
					reader.ReadEndElement();

					reader.ReadStartElement(NODE_VALUE);
					TValue value = (TValue)valueSerializer.Deserialize(reader);
					reader.ReadEndElement();
					
					// Add pair in dictionary
					ret.Add(key, value);
					
					reader.ReadEndElement();
					reader.MoveToContent();
				}
				reader.ReadEndElement();
			}
		}
		catch (Exception ex)
		{
			// Log error...
		}
		return ret;
	}
}

/******** Comment utiliser DictionarySerializer avec un Dictionary<string, string> **********/

const string KEY_FIRSTNAME = "firstName";
const string KEY_LASTNAME = "lastName";

/* Serialiser */
Dictionary<string, string> dicSource = new Dictionary<string, string>();
dicSource.Add(KEY_FIRSTNAME, "MaX");
dicSource.Add(KEY_LASTNAME, "TheOnly");
// etc.
string xml = DictionarySerializer<string, string>.ObjectToXml(dicSource);

/* Déserialiser */
string firstName, lastName;
Dictionary<string, string> dicResult = DictionarySerializer<string, string>.XmlToObject(xml);
if (dicResult != null)
{
    dicResult.TryGetValue(KEY_FIRSTNAME, out firstName);
    dicResult.TryGetValue(KEY_LASTNAME, out lastName);
	// etc.
}

/******** Résultat XML ***********/
<?xml version="1.0" encoding="utf-16"?>
<root>
  <item>
    <key>
      <string>firstName</string>
    </key>
    <value>
      <string>MaX</string>
    </value>
  </item>
  <item>
    <key>
      <string>lastName</string>
    </key>
    <value>
      <string>TheOnly</string>
    </value>
  </item>
</root>

Conclusion :


Voici un exemple avec une classe Personne :

[Serializable]
[XmlRoot]
public class Personne
{
private Personne()
{
// Indispensable pour la serialization
}

public Personne(string nom, int age)
{
this.Nom = nom;
this.Age = age;
}

[System.Xml.Serialization.XmlElement(ElementName = "nom")]
public String Nom { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "age")]
public int Age { get; set; }
}

// Code client :

Dictionary<string, Personne> dic = new Dictionary<string, Personne>();
dic.Add("personne 1", new Personne("Sylvain", 54));
dic.Add("personne 2", new Personne("Adrien", 32));

string xml = ULXmlSerializer<string, Personne>.ObjectToXml(dic);
Dictionary<string, Personne> ret = ULXmlSerializer<string, Personne>.XmlToObject(xml);

// Xml généré :

<?xml version="1.0" encoding="utf-16"?>
<root>
<item>
<key>
<string>personne 1</string>
</key>
<value>
<Personne xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<nom>Sylvain</nom>
<age>54</age>
</Personne>
</value>
</item>
<item>
<key>
<string>personne 2</string>
</key>
<value>
<Personne xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<nom>Adrien</nom>
<age>32</age>
</Personne>
</value>
</item>
</root>

A voir également