webentwicklung-frage-antwort-db.com.de

Serialisieren Sie ein Objekt in eine Zeichenfolge

Ich habe die folgende Methode, um ein Objekt in einer Datei zu speichern:

// 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();
}

Ich gestehe, dass ich es nicht geschrieben habe (ich habe es nur in eine Erweiterungsmethode konvertiert, die einen Typparameter übernommen hat).

Jetzt brauche ich es, um mir die XML-Datei als String zurückzugeben (anstatt sie in einer Datei zu speichern). Ich untersuche es, aber ich habe es noch nicht herausgefunden.

Ich dachte, das könnte für jemanden, der mit diesen Objekten vertraut ist, sehr einfach sein. Wenn nicht, werde ich es schließlich herausfinden.

264
Vaccano

Verwenden Sie eine StringWriter anstelle einer StreamWriter :

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

    using(StringWriter textWriter = new StringWriter())
    {
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }
}

Beachten Sie, dass es wichtig ist, toSerialize.GetType() anstelle von typeof(T) im XmlSerializer-Konstruktor zu verwenden: Wenn Sie den ersten verwenden, deckt der Code alle möglichen Unterklassen von T ab (die für die Methode gültig sind). Die Verwendung der letzteren schlägt fehl, wenn ein abgeleiteter Typ übergeben wird von T. Hier ein Link mit Beispielcode, der diese Anweisung motiviert, wobei XmlSerializer eine Exception auslöst, wenn typeof(T) verwendet wird, da Sie eine Instanz eines abgeleiteten Typs an eine Methode übergeben, die das in der Basisklasse des abgeleiteten Typs definierte SerializeObject aufruft : http://ideone.com/1Z5J1 .

Ideone verwendet auch Mono, um Code auszuführen. Die tatsächliche Exception, die Sie bei Verwendung der Microsoft .NET-Laufzeitumgebung erhalten würden, hat eine andere Message als die in Ideone angezeigte. Sie schlägt jedoch genauso fehl.

463
dtb

Ich weiß, dass dies nicht wirklich eine Antwort auf die Frage ist, aber basierend auf der Anzahl der Stimmen für die Frage und der akzeptierten Antwort vermute ich, dass die Leute den Code tatsächlich verwenden, um ein Objekt in eine Zeichenfolge zu serialisieren.

Die Verwendung von XML-Serialisierung fügt der Ausgabe unnötigen zusätzlichen Textabfall hinzu.

Für die folgende Klasse

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

es erzeugt 

<?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>

Eine bessere Lösung ist die Verwendung der JSON-Serialisierung (eine der besten Methoden ist Json.NET ) . So serialisieren Sie ein Objekt:

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

Um ein Objekt zu deserialisieren:

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

Die serialisierte JSON-Zeichenfolge würde folgendermaßen aussehen:

{"UserId":0}
66
xhafan

Serialisieren und Deserialisieren:

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

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

Code Sicherheitshinweis

In Bezug auf die akzeptierte Antwort ist es wichtig, toSerialize.GetType() anstelle von typeof(T) im XmlSerializer-Konstruktor zu verwenden: Wenn Sie den ersten verwenden, deckt der Code alle möglichen Szenarien ab, während der letztere manchmal ausfällt. 

Hier ist ein Link mit Beispielcode, der diese Anweisung motiviert. XmlSerializer löst eine Exception aus, wenn typeof(T) verwendet wird, weil Sie eine Instanz eines abgeleiteten Typs an eine Methode übergeben, die SerializeObject<T>() aufruft, die in der Basisklasse des abgeleiteten Typs definiert ist: http://ideone.com/1Z5J1 . Beachten Sie, dass Ideone zur Ausführung von Code Mono verwendet: Die tatsächliche Ausnahme, die Sie bei Verwendung der Microsoft .NET-Laufzeitumgebung erhalten würden, hat eine andere Nachricht als die in Ideone gezeigte, sie schlägt jedoch fehl. 

Der Vollständigkeit halber gebe ich hier das vollständige Codebeispiel als Referenz für den Fall auf, dass Ideone (wo ich den Code gepostet habe) in der Zukunft nicht mehr verfügbar ist:

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();
    }
}
37
Fulvio

Mein 2p ...

        string Serialise<T>(T serialisableObject)
        {
            var xmlSerializer = new XmlSerializer(serialisableObject.GetType());

            using (var ms = new MemoryStream())
            {
                using (var xw = XmlWriter.Create(ms, 
                    new XmlWriterSettings()
                        {
                            Encoding = new UTF8Encoding(false),
                            Indent = true,
                            NewLineOnAttributes = true,
                        }))
                {
                    xmlSerializer.Serialize(xw,serialisableObject);
                    return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
        }
10
oPless
public static string SerializeObject<T>(T objectToSerialize)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            MemoryStream memStr = new MemoryStream();

            try
            {
                bf.Serialize(memStr, objectToSerialize);
                memStr.Position = 0;

                return Convert.ToBase64String(memStr.ToArray());
            }
            finally
            {
                memStr.Close();
            }
        }

        public static T DerializeObject<T>(string objectToDerialize)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            byte[] byteArray = Convert.FromBase64String(objectToDerialize);
            MemoryStream memStr = new MemoryStream(byteArray);

            try
            {
                return (T)bf.Deserialize(memStr);
            }
            finally
            {
                memStr.Close();
            }
        }
4
teapeng

Ich konnte die von Xhafan vorgeschlagene JSONConvert-Methode nicht verwenden

In .NET 4.5 konnte ich nach dem Hinzufügen der Assembly-Referenz "System.Web.Extensions" immer noch nicht auf den JSONConvert zugreifen.

Sobald Sie jedoch die Referenz hinzugefügt haben, können Sie die gleiche Zeichenfolge ausdrucken, indem Sie Folgendes verwenden:

JavaScriptSerializer js = new JavaScriptSerializer();
string jsonstring = js.Serialize(yourClassObject);
1
Thomas Tiveron

Ich hatte das Gefühl, dass ich diesen manipulierten Code der akzeptierten Antwort mitteilen musste. Da ich keinen guten Ruf habe, kann ich nicht kommentieren ...

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

namespace ObjectSerialization
{
    public static class ObjectSerialization
    {
        // THIS: (C): https://stackoverflow.com/questions/2434534/serialize-an-object-to-string
        /// <summary>
        /// A helper to serialize an object to a string containing XML data of the object.
        /// </summary>
        /// <typeparam name="T">An object to serialize to a XML data string.</typeparam>
        /// <param name="toSerialize">A helper method for any type of object to be serialized to a XML data string.</param>
        /// <returns>A string containing XML data of the object.</returns>
        public static string SerializeObject<T>(this T toSerialize)
        {
            // create an instance of a XmlSerializer class with the typeof(T)..
            XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());

            // using is necessary with classes which implement the IDisposable interface..
            using (StringWriter stringWriter = new StringWriter())
            {
                // serialize a class to a StringWriter class instance..
                xmlSerializer.Serialize(stringWriter, toSerialize); // a base class of the StringWriter instance is TextWriter..
                return stringWriter.ToString(); // return the value..
            }
        }

        // THIS: (C): VPKSoft, 2018, https://www.vpksoft.net
        /// <summary>
        /// Deserializes an object which is saved to an XML data string. If the object has no instance a new object will be constructed if possible.
        /// <note type="note">An exception will occur if a null reference is called an no valid constructor of the class is available.</note>
        /// </summary>
        /// <typeparam name="T">An object to deserialize from a XML data string.</typeparam>
        /// <param name="toDeserialize">An object of which XML data to deserialize. If the object is null a a default constructor is called.</param>
        /// <param name="xmlData">A string containing a serialized XML data do deserialize.</param>
        /// <returns>An object which is deserialized from the XML data string.</returns>
        public static T DeserializeObject<T>(this T toDeserialize, string xmlData)
        {
            // if a null instance of an object called this try to create a "default" instance for it with typeof(T),
            // this will throw an exception no useful constructor is found..
            object voidInstance = toDeserialize == null ? Activator.CreateInstance(typeof(T)) : toDeserialize;

            // create an instance of a XmlSerializer class with the typeof(T)..
            XmlSerializer xmlSerializer = new XmlSerializer(voidInstance.GetType());

            // construct a StringReader class instance of the given xmlData parameter to be deserialized by the XmlSerializer class instance..
            using (StringReader stringReader = new StringReader(xmlData))
            {
                // return the "new" object deserialized via the XmlSerializer class instance..
                return (T)xmlSerializer.Deserialize(stringReader);
            }
        }

        // THIS: (C): VPKSoft, 2018, https://www.vpksoft.net
        /// <summary>
        /// Deserializes an object which is saved to an XML data string.
        /// </summary>
        /// <param name="toDeserialize">A type of an object of which XML data to deserialize.</param>
        /// <param name="xmlData">A string containing a serialized XML data do deserialize.</param>
        /// <returns>An object which is deserialized from the XML data string.</returns>
        public static object DeserializeObject(Type toDeserialize, string xmlData)
        {
            // create an instance of a XmlSerializer class with the given type toDeserialize..
            XmlSerializer xmlSerializer = new XmlSerializer(toDeserialize);

            // construct a StringReader class instance of the given xmlData parameter to be deserialized by the XmlSerializer class instance..
            using (StringReader stringReader = new StringReader(xmlData))
            {
                // return the "new" object deserialized via the XmlSerializer class instance..
                return xmlSerializer.Deserialize(stringReader);
            }
        }
    }
}

0