359 votes

Sérialiser un objet à une chaîne

J'ai la méthode suivante pour enregistrer un objet dans un fichier:

 // Save an object out to the disk
public static void SerializeObject<T>(this T toSerialize, String filename)
{
    XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
    TextWriter textWriter = new StreamWriter(filename);

    xmlSerializer.Serialize(textWriter, toSerialize);
    textWriter.Close();
}
 

J'avoue que je ne l'ai pas écrit (je l'ai seulement converti en une méthode d'extension qui prenait un paramètre de type).

Maintenant j'en ai besoin pour me redonner le xml sous forme de chaîne (plutôt que de l'enregistrer dans un fichier). Je regarde dedans, mais je ne l'ai pas encore compris.

J'ai pensé que cela pourrait être très facile pour quelqu'un qui connaît ces objets. Sinon, je finirai par le comprendre.

615voto

dtb Points 104373

Utiliser un StringWriter au lieu de StreamWriter:

public static string SerializeObject<T>(this T toSerialize)
{
    XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
    StringWriter textWriter = new StringWriter();

    xmlSerializer.Serialize(textWriter, toSerialize);
    return textWriter.ToString();
}

Remarque, il est important d'utiliser toSerialize.GetType() au lieu de typeof(T) dans le constructeur de XmlSerializer: si vous utiliser le code couvre toutes les sous-classes de T (valable pour la méthode), tout en utilisant la dernière échoue lors du passage d'un type dérivé de T. Voici un lien avec un exemple de code qui motivent cette affirmation, XmlSerializer jetant un Exception lorsque typeof(T) est utilisé, parce que vous passez une instance d'un type dérivé à une méthode qui appelle SerializeObject qui est défini dans le type dérivé de la classe de base: http://ideone.com/1Z5J1.

Aussi, Ideone utilise Mono afin d'exécuter du code; le Exception vous souhaitez obtenir l'aide de Microsoft .NET est différente Message que celui indiqué sur Ideone, mais il échoue tout de même.

91voto

ADM-IT Points 51

Sérialiser et désérialiser:

     public static object DeserializeObject<T>(this string toDeserialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringReader textReader = new StringReader(toDeserialize);
        return xmlSerializer.Deserialize(textReader);
    }

    public static string SerializeObject<T>(this T toSerialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringWriter textWriter = new StringWriter();
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }
 

76voto

xhafan Points 544

Je sais que ce n'est pas vraiment une réponse à la question, mais sur la base du nombre de votes pour la question et que l'on a accepté la réponse, je suppose que les gens sont en fait en utilisant le code de sérialiser un objet en chaîne de caractères.

En utilisant la sérialisation XML ajoute supplémentaires inutiles texte déchets à la sortie.

Pour la classe suivante

public class UserData
{
    public int UserId { get; set; }
}

il génère

<?xml version="1.0" encoding="utf-16"?>
<UserData xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <UserId>0</UserId>
</UserData>

La meilleure solution est d'utiliser la sérialisation JSON (l'un des meilleurs est Json.NET). Pour sérialiser un objet:

var userData = new UserData {UserId = 0};
var userDataString = JsonConvert.SerializeObject(userData);

Pour désérialiser un objet:

var userData = JsonConvert.DeserializeObject<UserData>(userDataString);

Le sérialisé chaîne JSON ressemblerait à:

{"UserId":0}

38voto

Fulvio Points 744

Code De Sécurité

Quant à la accepté de répondre, il est important d'utiliser toSerialize.GetType() au lieu de typeof(T) en XmlSerializer constructeur: si vous utiliser le code couvre tous les scénarios possibles, tout en utilisant la dernière échoue parfois.

Voici un lien avec un exemple de code qui motivent cette affirmation, XmlSerializer lancement d'une Exception lors de l' typeof(T) est utilisé, parce que vous passez une instance d'un type dérivé à une méthode qui appelle SerializeObject<T>() qui est défini dans le type dérivé de la classe de base: http://ideone.com/1Z5J1. Notez que Ideone utilise Mono afin d'exécuter du code: l'Exception réelle vous souhaitez obtenir l'aide de Microsoft .NET runtime a un Message différent que celui indiqué sur Ideone, mais il échoue tout de même.

Par souci d'exhaustivité, je poste le code complet de l'échantillon ici pour référence future, juste au cas où Ideone (où j'ai posté le code) devient disponible dans le futur:

using System;
using System.Xml.Serialization;
using System.IO;

public class Test
{
    public static void Main()
    {
        Sub subInstance = new Sub();
        Console.WriteLine(subInstance.TestMethod());
    }

    public class Super
    {
        public string TestMethod() {
            return this.SerializeObject();
        }
    }

    public class Sub : Super
    {
    }
}

public static class TestExt {
    public static string SerializeObject<T>(this T toSerialize)
    {
        Console.WriteLine(typeof(T).Name);             // PRINTS: "Super", the base/superclass -- Expected output is "Sub" instead
        Console.WriteLine(toSerialize.GetType().Name); // PRINTS: "Sub", the derived/subclass

        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringWriter textWriter = new StringWriter();

        // And now...this will throw and Exception!
        // Changing new XmlSerializer(typeof(T)) to new XmlSerializer(subInstance.GetType()); 
        // solves the problem
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }
}

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