Benutzerdefinierte Xml-Serialisierung von Unbekannter Typ
Versuche ich zu Deserialisieren eine benutzerdefinierte Klasse mit dem XmlSerializer und ein paar Probleme in der Tatsache, dass ich weiß nicht, den Typ, ich werde Deserialisieren (ist steckbar), und ich habe Schwierigkeiten bei der Bestimmung.
Fand ich dieser Beitrag, die sieht ähnlich aus, kann aber nicht ganz zum laufen bekommen mit meinem Ansatz, denn ich muss Deserialisieren eine Schnittstelle, die XmlSerializable.
Was ich derzeit habe ist von der form. Beachten Sie, dass ich erwarten und müssen in der Lage sein zu handhaben, sowohl in der Klasse A und der Klasse B umgesetzt werden über ein plugin. Also, wenn ich kann vermeiden Sie die IXmlSerializable - (was-glaube ich-nicht kann), dann wäre das großartig.
Den ReadXml für Eine ist das, was ich stecken geblieben bin. Jedoch, wenn dort sind andere änderungen, die ich machen kann um das system zu verbessern, dann bin ich glücklich, dies zu tun.
public class A : IXmlSerializable
{
public IB MyB { get; set;}
public void ReadXml(System.Xml.XmlReader reader)
{
//deserialize other member attributes
SeekElement(reader, "MyB");
string typeName = reader.GetAttribute("Type");
//Somehow need to the type based on the typename. From potentially
//an external assembly. Is it possible to use the extra types passed
//into an XMlSerializer Constructor???
Type bType = ???
//Somehow then need to deserialize B's Members
//Deserialize X
//Deserialize Y
}
public void WriteXml(System.Xml.XmlWriter writer)
{
//serialize other members as attributes
writer.WriteStartElement("MyB");
writer.WriteAttributeString("Type", this.MyB.GetType().ToString());
this.MyB.WriteXml(writer);
writer.WriteEndElement();
}
private void SeekElement(XmlReader reader, string elementName)
{
ReaderToNextNode(reader);
while (reader.Name != elementName)
{
ReaderToNextNode(reader);
}
}
private void ReaderToNextNode(XmlReader reader)
{
reader.Read();
while (reader.NodeType == XmlNodeType.Whitespace)
{
reader.Read();
}
}
}
public interface IB : IXmlSerializable
{
}
public class B : IB
{
public void ReadXml(XmlReader reader)
{
this.X = Convert.ToDouble(reader.GetAttribute("x"));
this.Y = Convert.ToDouble(reader.GetAttribute("y"));
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("x", this.X.ToString());
writer.WriteAttributeString("y", this.Y.ToString());
}
}
HINWEIS : Aktualisiert, als ich merkte, B soll um Schnittstelle zu verwenden, IB. Sorry für die etwas falsche Frage.
InformationsquelleAutor Ian | 2009-07-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erstellen Sie eine Instanz aus einem string, verwenden Sie eine der überladungen der Aktivator.CreateInstance. Nur ein Typ, name, Art der Benutzung.GetType.
Ich antwortete auf Ihren Kommentar, wo Sie sagte: "Irgendwie muss der Typ basierend auf dem Typnamen."
Danke, John. Durch das Auslesen der Typ aus dem XML, erstellen einer Instanz war ich dann in der Lage zu de-serialisieren mit der ReadXml-Methode des erzeugten Instanz. Arbeitet ein Genuss und funktioniert einwandfrei mit meinem Interface.
InformationsquelleAutor John Saunders
Ich glaube nicht, dass Sie brauchen, um zu implementieren
IXmlSerializable
...Da Sie nicht wissen, die tatsächlichen Typen vor der Laufzeit, Sie können dynamisch hinzufügen-Attribut überschreibt, um dem XmlSerializer. Sie müssen nur wissen, die Liste der Arten, die Erben von A. Zum Beispiel, wenn Sie Eine als eine Eigenschaft einer anderen Klasse :
Können Sie dynamisch gelten
XmlElementAttribute
s für jeden abgeleiteten Typ, Eigenschaft :Ist dies nur ein sehr einfaches Beispiel, aber es zeigt, wie die Anwendung der XML-Serialisierung Attribute zur Laufzeit, wenn Sie nicht tun können, statisch.
Nein, leider ist die XML-Serialisierung nicht serialisieren Schnittstellen... in diesem Fall fürchte ich, dass Sie verwenden, IXmlSerializable.
Ja, das dachte ich mir... ich fange an zu Fragen, ob vielleicht mein interface sollte stattdessen eine abstrakte Klasse. Ich nehme an, dann würde es auch funktionieren und Hierarchien von Klassen (z.B. B implemeneting AbstractB) würde deserialisiert werden, statt den Versuch zu Deserialisieren eines AbstractB direkt.
Ja, einfacher wäre es mit einer abstrakten Klasse...
InformationsquelleAutor Thomas Levesque
Ich würde xpath verwenden, um schnell herauszufinden, ob die xml-Eingabe enthält die Klasse A oder Klasse B. Dann Deserialisieren es, basierend auf, dass.
heh, hey, ich bin ein sql-junkie, aber auch ich war schon Weg von den eher exotischen Funktionen von xpath... 🙂
Könnten Sie ein sehr kurzes Beispiel? Ich habe nicht wirklich verwendet xpath. Nur Frage mich, ob es lohnt ein Blick in. Wollte auf den Umgang mit den XML direkt so wenig wie möglich aber.
InformationsquelleAutor Arnshea