web-dev-qa-db-fra.com

Pourquoi XmlSerializer ne prend-il pas en charge Dictionary?

Vous êtes curieux de savoir pourquoi le dictionnaire n'est pas pris en charge par XmlSerializer?

Vous pouvez le contourner assez facilement en utilisant DataContractSerializer et en écrivant l'objet dans un XmlTextWriter, mais quelles sont les caractéristiques d'un dictionnaire qui compliquent la tâche d'un XmlSerializer en considérant que c'est vraiment un tableau de paires de valeurs clés.

En fait, vous pouvez passer un IDictionary<TKey, TItem> vers une méthode qui attend un IEnumerable<KeyValuePairs<TKey, ITem>>.

46
theburningmonk

Les tables de hachage ont généralement besoin de fournisseurs de codes de hachage et de comparateurs d'égalité. Ceux-ci ne peuvent pas être sérialisés facilement en XML et ne seront certainement pas portables.

Mais je pense que vous avez déjà trouvé votre réponse. Sérialisez simplement la table de hachage comme List<KeyValuePair<K,V>> puis (re) construire en une table de hachage.

27
leppie

C'est un peu tard - mais j'ai trouvé cette question en cherchant moi-même la réponse, et j'ai pensé partager ma réponse finale qui était de remplacer XmlSerializer par un outil différent qui sérialisera tout:

http://www.sharpserializer.com

Cela a fonctionné pour moi tout de suite, sérialisant les dictionnaires et les types personnalisés à plusieurs couches, et même les génériques utilisant des interfaces comme arguments de type. Possède également une licence entièrement permissive.

Merci Pawel Idzikowski!

7
Nich Overend

Vous pouvez utiliser ExtendedXmlSerializer . Si vous avez un cours:

public class TestClass
{
    public Dictionary<int, string> Dictionary { get; set; }
}

et créer une instance de cette classe:

var obj = new TestClass
{
    Dictionary = new Dictionary<int, string>
    {
        {1, "First"},
        {2, "Second"},
        {3, "Other"},
    }
};

Vous pouvez sérialiser cet objet en utilisant ExtendedXmlSerializer:

var serializer = new ConfigurationContainer()
    .UseOptimizedNamespaces() //If you want to have all namespaces in root element
    .Create();

var xml = serializer.Serialize(
    new XmlWriterSettings { Indent = true }, //If you want to formated xml
    obj);

Le XML de sortie ressemblera à:

<?xml version="1.0" encoding="utf-8"?>
<TestClass xmlns:sys="https://extendedxmlserializer.github.io/system" xmlns:exs="https://extendedxmlserializer.github.io/v2" xmlns="clr-namespace:ExtendedXmlSerializer.Samples;Assembly=ExtendedXmlSerializer.Samples">
  <Dictionary>
    <sys:Item>
      <Key>1</Key>
      <Value>First</Value>
    </sys:Item>
    <sys:Item>
      <Key>2</Key>
      <Value>Second</Value>
    </sys:Item>
    <sys:Item>
      <Key>3</Key>
      <Value>Other</Value>
    </sys:Item>
  </Dictionary>
</TestClass>

Vous pouvez installer ExtendedXmlSerializer à partir de nuget ou exécuter la commande suivante:

Install-Package ExtendedXmlSerializer
3
Wojtpl2