120 votes

.NET la sérialisation XML pièges?

J'ai rencontré quelques problèmes lors de C# sérialisation XML j'ai pensé que je pourrais partager avec vous:


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

[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{      
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

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

            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

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

            writer.WriteEndElement();
        }
    }
}

Toute autre Sérialisation XML erreurs?

27voto

Kalid Points 6290

Un autre énorme gotcha: lors de la sortie XML dans une page web (ASP.NET), vous ne voulez pas inclure l' Unicode Marque d'Ordre d'Octet. Bien sûr, la manière de les utiliser ou ne pas utiliser la NOMENCLATURE sont presque les mêmes:

MAUVAIS (comprend BOM):

XmlTextWriter wr = new XmlTextWriter(stream, new System.Text.Encoding.UTF8);

BON:

XmlTextWriter  wr = new XmlTextWriter(stream, new System.Text.UTF8Encoding(false))

Vous pouvez transmettre explicitement false pour indiquer que vous ne voulez pas de la NOMENCLATURE. Avis clair, la différence la plus évidente entre Encoding.UTF8 et UTF8Encoding.

Les trois NOMENCLATURE Octets au début (0xEFBBBF) ou (239 187 191).

Référence: http://chrislaco.com/blog/troubleshooting-common-problems-with-the-xmlserializer/

21voto

Charles Graham Points 8132

Je ne peux pas faire de commentaires pour l'instant, donc je ne vais commenter Dr8k la poste et faire une autre observation. Variables privées qui sont exposées en public propriétés de lecture/définition, et n'être sérialisé/désérialisé en tant que tels par le biais de ces propriétés. Nous l'avons fait dans mon ancien job al dans le temps.

Une chose à noter est que si vous avez la moindre logique dans ces propriétés, la logique est exécuté, donc, parfois, de l'ordre de sérialisation des questions. Les membres sont implicitement commandé par la façon dont ils sont organisés dans le code, mais il n'y a pas de garanties, en particulier lorsque vous héritez d'un autre objet. Explicitement les commander est une douleur à l'arrière.

J'ai été brûlé par les ce dans le passé.

15voto

realgt Points 1181

Lors de la sérialisation dans une chaîne XML à partir d'un flux de mémoire, assurez-vous d'utiliser MemoryStream#ToArray() au lieu de MemoryStream#GetBuffer() ou vous allez vous retrouver avec des caractères indésirables qui ne sont pas désérialiser correctement (à cause de la surcharge de la mémoire tampon allouée).

http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(SV.80).aspx

8voto

Tim Robinson Points 28696

Vous ne pouvez pas sérialiser des propriétés en lecture seule. Vous devez avoir un getter et un setter, même si vous n'avez jamais l'intention d'utiliser la désérialisation de transformer des données XML dans un objet.

Pour la même raison, vous ne pouvez pas sérialiser propriétés que le retour des interfaces: la deserializer ne sais pas ce béton de la classe à instancier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X