Die XML-Serialisierung in .NET ermöglicht polymorphe Objekte über den Parameter extraTypes[]
des Konstruktors XmlSerializer
. Es ermöglicht auch die Anpassung der XML-Serialisierung für Typen, die IXmlSerializable
implementieren.
Allerdings kann ich diese beiden Funktionen nicht kombinieren - wie in diesem minimalen Beispiel gezeigt:
%Vor% Die letzte Zeile zeigt System.InvalidOperationException
mit dieser Nachricht an:
Der Typ CsFoo.CustomSerializable darf in diesem Kontext nicht verwendet werden Verwenden Sie CsFoo.CustomSerializable als Parameter, return Typ oder Mitglied einer Klasse oder Struktur, der Parameter return type oder member muss als Typ CsFoo.CustomSerializable deklariert werden (Es kann nicht Objekt sein). Objekte vom Typ CsFoo.CustomSerializable kann nicht in nicht typisierten Auflistungen wie ArrayLists verwendet werden.
Wenn wir durch die dynamisch generierten XML-Assemblies blättern, kommen wir letztendlich zurück zum .NET-Standardbibliothekscode, indem wir aufrufen:
%Vor%Dies führt wiederum zu:
%Vor% Reflector zeigt, dass die XmlInvalidSerializable
Ressource der obigen Zeichenfolge entspricht - d. h. WriteTypedPrimitive
mag IXmlSerializable
nicht.
Wenn wir einen nicht-polymorphen Serializer erzeugen, so:
%Vor%.NET generiert einen Aufruf an:
%Vor% Dies behandelt IXmlSerializable
richtig. Weiß jemand, warum .NET diese Funktion nicht im polymorphen Fall verwendet? Betrachtet man die C #, die der XML-Serializer erzeugt, so scheint mir dies relativ einfach zu sein. Hier ist ein Code, den ich vom XML-Serializer bekommen habe, mit einer nicht getesteten Lösung:
Ist dies aus technischen Gründen oder nur eine Funktionseinschränkung weggelassen? Nicht unterstützte Funktion oder meine Idiotie? Meine Intertubes Google-Fähigkeiten scheitern mir.
Ich habe einige verwandte Fragen hier gefunden, mit " C # Xml- Serialisieren einer abgeleiteten Klasse mit IXmlSerializable "ist am relevantesten. Es lässt mich glauben, dass es einfach nicht möglich ist.
In diesem Fall besteht mein aktueller Gedanke darin, eine Standardprozedur IXmlSerializable
in die Root-Basisklasse zu injizieren. Dann wird alles ein IXmlSerializable
, und .NET wird sich nicht beschweren. Ich kann Reflection.Emit verwenden, um die Körpern ReadXml
und WriteXml
für jeden konkreten Typ auszulöschen, wobei XML erzeugt wird, das genauso aussehen würde wie wenn ich die Bibliothek verwenden würde.
Einige Leute denken, wenn sie mit einem XML-Serialisierungsproblem konfrontiert werden: "Ich weiß, ich benutze Reflection.Emit, um Code zu generieren." Jetzt haben sie zwei Probleme.
P.S. Hinweis; Ich kenne Alternativen zu .NETs XML-Serialisierung und weiß, dass es Einschränkungen gibt. Ich weiß auch, dass das Speichern eines POCO wesentlich einfacher ist als der Umgang mit abstrakten Datentypen. Aber ich habe einen Stapel Legacy-Code und brauche Unterstützung für bestehende XML-Schemas.
So wie ich Antworten schätze, die zeigen, wie einfach das ist in SomeOtherXML
, YAML
, XAML
, ProtocolBuffers
, DataContract
, RandomJsonLibrary
, Thrift
oder Ihre MorseCodeBasedSerializeToMp3
library - hey ich könnte etwas lernen -, was ich hoffe, ist eine XML-Serializer Work-Around, wenn nicht Lösung.
Ich konnte Ihr Problem reproduzieren, wenn Sie object
verwenden:
Ich habe dann jedoch eine abgeleitete Klasse von CustomSerializable
erstellt:
Und versuchte es zu serialisieren:
%Vor%Das hat funktioniert.
Es scheint also, dass das Problem auf den Fall beschränkt ist, in dem Sie "object" als den zu serialisierenden Typ angeben, aber nicht, wenn Sie einen konkreten Basistyp angeben.
Ich werde am Morgen mehr darüber recherchieren.
Zuerst Poster Erklärung
Die XML-Serialisierung in .NET ermöglicht polymorphe Objekte über den Parameter extraTypes [] des XmlSerializer-Konstruktors.
ist irreführend. Laut MSDN wird extratypes für Folgendes verwendet:
Wenn eine Eigenschaft oder ein Array zurückgibt, gibt der Parameter extraTypes Objekte an, die in das Array eingefügt werden können.
Bedeutet, dass, wenn irgendwo in Ihrem serialisierten Objekt Graph polymorphe Objekte über ein Array zurückgegeben werden, diese verarbeitet werden können.
Obwohl ich nicht wirklich eine Lösung gefunden habe, wie man einen polymorphen Typ als root-XML-Objekt serialisiert, war ich in der Lage, polymorphe Typen im Objektgraphen zu serialisieren, entweder mit XML-Serialisierer oder IXmlSerializable. Siehe unten für meine Lösung:
%Vor%Beachten Sie, dass Sie entweder
verwenden %Vor%oder
%Vor%Ohne das definierte XmlElement würde der Code bei der Serialisierung fehlschlagen.
Damit IxmlSerializable funktioniert, muss die Klasse einen Nullkonstruktor haben.
Betrachten Sie eine Basisklasse
Tags und Links c# xml-serialization