[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

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.