2008-09-20 5 views
30

Ich möchte Objekte serialisieren und deserialisieren, ohne sich um das gesamte Klassendiagramm kümmern zu müssen.Was ist die flexibelste Serialisierung für .NET-Objekte, aber einfach zu implementieren?

Flexibilität ist der Schlüssel. Ich möchte in der Lage sein, jedes Objekt, das an mich übergeben wird, ohne vollständige Attribute, die für das gesamte Objektdiagramm benötigt werden, zu serialisieren.

Das bedeutet, dass binäre Serialisierung keine Option ist, da es nur mit den anderen .NET-Plattformen funktioniert. Ich würde auch gerne etwas von einer Person lesbar und damit durch ein Management-Programm und andere Dolmetscher dechiffrierbar.

Ich habe Probleme mit den DataContract, JSON und XML-Serialisierer gefunden.

  • Die meisten dieser Fehler scheinen sich um die Serialisierung von Listen/Wörterbüchern zu drehen (d. H. XML Serializable Generic Dictionary).
  • „Fügen Sie alle Arten nicht bekannt statisch in die Liste der bekannten Typen - für Beispiel unter Verwendung des Knowntype Attribut oder durch sie in die Liste der bekannten Typen Hinzufügen zu DataContractSerializer übergeben.“
  • Bitte basieren Sie Ihre Antworten auf tatsächlichen Erfahrungen und nicht Theorie oder Lesen eines Artikels.

    Antwort

    53

    kopiert zu serialisiert wäre Haben Sie darüber nachgedacht zu JSON Serialisierung anstelle von XML?

    Json.NET hat einen wirklich leistungsfähigen und flexiblen Serializer, der keine Probleme mit Hashtables/generischen Wörterbüchern hat und keine besonderen Attribute benötigt. Ich weiß, weil ich es geschrieben habe :)

    Es gibt Ihnen eine Menge Kontrolle durch verschiedene Optionen auf dem Serializer und es ermöglicht Ihnen, überschreiben, wie ein Typ serialisiert wird, indem Sie einen JsonConverter dafür erstellen.

    Meiner Meinung nach ist JSON menschlicher lesbarer als XML und Json.NET bietet die Möglichkeit, gut formatierte JSON zu schreiben.

    Schließlich ist das Projekt Open Source, so dass Sie in den Code einsteigen und bei Bedarf Änderungen vornehmen können.

    +0

    Ich habe dies versucht, und es gab mir bessere Fehler Ergebnisse als die Out-of-the-Box DataManinulator JSON Serializer, aber es bombardiert immer noch wegen einer Schleife Referenz. Irgendwelche Tipps? Ich baue ein Messaging-Framework und habe nicht viel Kontrolle über die tatsächliche Struktur eines Objekts. – mrbradleyt

    +1

    Setzen Sie die ReferenceLoopHandling-Eigenschaft für JsonSerializer auf Ignore. –

    +6

    Ich benutze JSON.Net - es rockt total !!!!! –

    0

    Am einfachsten markieren Sie Ihre Objekte mit dem Serializable-Attribut und verwenden Sie dann einen binären Formatierer, um die Serialisierung zu behandeln. Das gesamte Klassendiagramm sollte kein Problem darstellen, vorausgesetzt, dass alle enthaltenen Objekte auch als serialisierbar gekennzeichnet sind.

    +0

    War nicht sicher, ob mbradleyt einige Teile des Klassengraphen ignorieren wollte, als er sagte, dass er sich nicht darum kümmern wollte. In diesem Fall müssen nicht alle Attribute serialisierbar sein (NonSerializedAttribute kann Felder markieren, die ausgeschlossen werden sollen) –

    +0

    Ja, Punkt vergeben. Er stellte auch klar, dass er ein nicht-binäres Format benötigt, also würde meine Lösung nicht für ihn funktionieren. –

    +0

    Der Fragesteller hat die binäre Serialisierung ausdrücklich ausgeschlossen. –

    1

    Der IntermediateSerializer im XNA Framework ist verdammt cool. Sie können es auf mit einer Reihe von Tutorials bei http://blogs.msdn.com/shawnhar

    +0

    Genauer gesagt, finden Sie alle Beiträge von Shawn zum Intermediate-Serialisierer hier: http://www.talula.demon.co.uk/blogindex.html#intermediateserializer –

    1

    SOAP-Serialisierung arbeiteten gut für mich, auch für Objekte, die nicht markiert mit [Serializable]

    +0

    Welche Klasse verwenden Sie? – mrbradleyt

    +0

    Ich glaube, die Verwendung der SOAP-Serialisierung wird von NET 2.0 abgeraten. Tatsächlich behandelt es nicht einmal Generika. http://social.msdn.microsoft.com/Forums/en-US/netfxremoting/thread/ee4a7a63-290e-432f-bd45-44f4cb7a3467/ –

    +0

    Irgendwo in Serialization.Formatters.Soap – ripper234

    2

    Von Ihren Anforderungen klingt es wie XML-Serialisierung am besten ist.

    Welche Art von Problemen haben Sie mit Sammlungen beim Serialisieren? Wenn Sie nicht wissen, welche Attribute in einer Liste oder ähnlichem verwendet werden sollen, können Sie das XmlArray-Attribut für Ihre Property verwenden. Sie können eine Sammlung definitiv serialisieren.

    +0

    Können Sie bitte näher auf die XmlArray Attribut ... Ich hatte Probleme mit Listen .... – mrbradleyt

    +0

    Sie benötigen das XmlArray-Attribut nicht wirklich, wenn Sie sgen verwenden. Das allgemeine Muster besteht darin, eine separate Klasse von der Liste abzuleiten und diese dann stattdessen zu serialisieren, statt z. [Serializable] public class YourObjectCollection: Liste { } Allerdings habe ich festgestellt, dass selbst das ist nicht nötig – ilitirit

    +0

    +1 ilitirit ist. Behebung eines Problems, das ich hatte, wo ich eine Liste nicht serialisieren konnte, ohne einen zusätzlichen Satz von Tags zu bekommen, die es umschlossen, so dass ich es nicht in ein DataSet einlesen konnte. –

    1

    Sie haben Probleme mit der Sammlungsserialisierung, wenn Objekte in der Sammlung einen Verweis auf andere Objekte in derselben Sammlung enthalten. Wenn eine Art von Dual-Pointing vorhanden ist, erstellen Sie eine Multi-Map, die nicht serialisiert werden kann. Bei jedem Problem, das ich jemals in einer benutzerdefinierten Sammlung serialisiert hatte, war es immer wegen einiger zusätzlicher Funktionen, die ich brauchte, die als Teil einer "typischen" Client-Server-Anwendung funktionierten und dann kläglich als Teil eines Verbraucheranbieters versagten -Server-Anwendung.

    3

    Wenn ich mich erinnere es funktioniert so etwas wie dies mit einer Eigenschaft:

    [XmlArray("Foo")] 
    [XmlArrayItem("Bar")] 
    public List<BarClass> FooBars 
    { get; set; } 
    

    Wenn Sie diese serialisiert Sie so etwas wie bekäme:

    <Foo> 
        <Bar /> 
        <Bar /> 
    </Foo> 
    

    Natürlich sollte ich wahrscheinlich auf die aufschieben Experten. Hier sind weitere Informationen von MS: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx

    Lassen Sie mich wissen, wenn das für Sie funktioniert.

    1

    Setzen Sie alle Klassen, die Sie serialisieren möchten, in eine separate Assembly, und verwenden Sie dann das sgen-Tool zum Generieren einer Serialisierungsassembly, um sie in XML zu serialisieren. Verwenden Sie XML-Attribute, um die Serialisierung zu steuern.

    Wenn Sie die Serialisierungsassembly anpassen (und Sie werden Notwendigkeit, die Klassen zu unterstützen, die nicht IXmlSerializable und Klassen sind die abstrakten Knoten enthalten), dann anweisen sgen den Quellcode in eine separate Datei zu entleeren und dann füge es zu deiner Lösung hinzu. Dann können Sie es bei Bedarf ändern.

    http://msdn.microsoft.com/en-us/library/bk3w6240(VS.80).aspx

    FWIW, habe ich es geschafft, die gesamte AdsML Framework (über 400 Klassen) mit dieser Technik serialisieren. Es erforderte eine Menge manuelle Anpassung, aber es kommt nicht herum, wenn man die Größe des Frameworks berücksichtigt. (Ich habe ein separates Tool von XSD zu C# gehen)

    0

    Vielleicht eine effizientere Route mit dem BinaryFormatter

    Wie aus http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/

    using System.IO; 
    using System.Runtime.Serialization; 
    using System.Runtime.Serialization.Formatters.Binary; 
    
    public class Serializer 
    { 
        public Serializer() 
        { 
        } 
    
        public void SerializeObject(string filename, 
            ObjectToSerialize objectToSerialize) 
        { 
         Stream stream = File.Open(filename, FileMode.Create); 
         BinaryFormatter bFormatter = new BinaryFormatter(); 
         bFormatter.Serialize(stream, objectToSerialize); 
         stream.Close(); 
        } 
    
        public ObjectToSerialize DeSerializeObject(string filename) 
        { 
         ObjectToSerialize objectToSerialize; 
         Stream stream = File.Open(filename, FileMode.Open); 
         BinaryFormatter bFormatter = new BinaryFormatter(); 
         objectToSerialize = 
         (ObjectToSerialize)bFormatter.Deserialize(stream); 
         stream.Close(); 
         return objectToSerialize; 
        } 
    } 
    
    0

    Für die Interoperabilität haben wir immer Xml-Serialisierung verwendet und sichergestellt, dass unsere Klasse von Grund auf neu entwickelt wurde, um es richtig zu machen.

    Wir erstellen ein XSD-Schemadokument und generieren daraus eine Gruppe von Klassen mit XSD.exe. Dies erzeugt partielle Klassen, so dass wir dann eine Menge entsprechender partieller Klassen erstellen, um die zusätzlichen Methoden hinzuzufügen, die uns helfen sollen, die Klassen zu füllen und sie in unserer Anwendung zu verwenden (da sie sich auf Serialisierung und Deserialisierung konzentrieren und manchmal schwierig zu verwenden sind)).

    0

    Sie sollten den NetDataContractSerializer verwenden.Sie deckt alle Arten von Objektgraphen ab und unterstützt Generika, Listen, Polymorphie (das Attribut KnownType wird hier nicht benötigt), Rekursion usw. Der einzige Nachteil ist, dass Sie alle Ihre Klassen mit [Serializable]/[DataContract] -Attributen markieren müssen , aber die Erfahrung zeigt, dass man sowieso eine manuelle Feinabstimmung durchführen muss, da nicht alle Mitglieder dauerhaft bleiben sollten. Auch serialisiert es in ein Xml, obwohl seine Lesbarkeit fraglich ist.

    Wir hatten die gleichen Anforderungen wie Ihre und wählten diese Lösung.

    1

    Ich stimme zu, dass die DataContract-basierte Serialisierungsmethoden (zu JSON, XML, usw.) ein bisschen komplexer ist, als ich möchte.

    Wenn Sie versuchen, JSON zu erhalten überprüfen http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

    Es ist ein Teil der MS AJAX-Erweiterungen. Zugegeben, es ist in .NET 3.5 als Obsolet gekennzeichnet, aber ScottGu erwähnt in seinem Blogkommentar hier (http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx#4301973), dass er nicht sicher ist warum und es sollte noch ein bisschen länger unterstützt werden.

    Verwandte Themen