La coutume de la Sérialisation Xml de Type Inconnu
Je suis d'essayer de désérialiser une classe personnalisée via le XmlSerializer et le fait d'avoir quelques problèmes, dans le fait que je ne connais pas le type que je vais être la désérialisation (enfichable) et je vais avoir de la difficulté à déterminer.
J'ai trouvé ce post qui lui ressemble, mais n'arrive pas à le faire fonctionner avec ma démarche car j'ai besoin de désérialiser une interface qui est XmlSerializable.
Ce que j'ai actuellement obtenu est de la forme. Notez que j'attends et doivent être en mesure de gérer à la fois de la classe A et de classe B à être mis en œuvre par l'intermédiaire d'un plugin. Donc si je peux éviter d'utiliser le IXmlSerializable (dont je ne pense pas que je peux), alors ce serait génial.
La ReadXml pour Un est ce que je suis coincé sur. Cependant, si il y a d'autres changements que je peux faire pour améliorer le système, alors je suis heureux de le faire.
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());
}
}
REMARQUE : le Jour que j'ai réalisé que B était censé utiliser l'interface de l'IB. Désolé un peu de mal question.
OriginalL'auteur Ian | 2009-07-02
Vous devez vous connecter pour publier un commentaire.
Pour créer une instance à partir d'une chaîne, utilisez l'une des surcharges de l'Activateur.CreateInstance. Pour obtenir juste un type avec un nom, le Type d'utilisation.GetType.
J'ai été de répondre à votre commentaire où vous avez dit "en Quelque sorte besoin pour le type de la propriété typename."
Merci John. Par la lecture du type de XML, la création d'une instance j'ai ensuite été en mesure de le sérialiser l'aide de la méthode ReadXml de l'instance créée. Fonctionne un régal et fonctionne très bien avec mon Interface.
OriginalL'auteur John Saunders
Je ne pense pas que vous avez besoin pour mettre en œuvre
IXmlSerializable
...Car vous ne savez pas les types réels avant l'exécution, vous pouvez ajouter dynamiquement attribut remplace le XmlSerializer. Vous avez juste besoin de connaître la liste des types qui hérite de A. Par exemple, si vous utilisez Un en tant que propriété d'une autre classe :
Vous pouvez appliquer de manière dynamique
XmlElementAttribute
s pour chaque type dérivé de cette propriété :C'est juste un exemple de base, mais il montre comment appliquer des attributs de sérialisation XML au moment de l'exécution lorsque vous ne pouvez pas le faire de manière statique.
Non, malheureusement, la sérialisation XML n'est pas sérialiser des interfaces... dans ce cas, je crains que vous devrez utiliser IXmlSerializable.
Ouais, je pensais comme beaucoup... je commence à me demander si peut-être mon interface devrait plutôt être une classe abstraite. Je suis en supposant que ce ne serait alors le travail et les hiérarchies de classes (par exemple, B implemeneting AbstractB) serait désérialisé, plutôt que d'essayer de désérialiser un AbstractB directement.
Oui, il serait plus simple avec une classe abstraite...
OriginalL'auteur Thomas Levesque
J'utilise xpath pour déterminer rapidement si l'entrée xml contient de classe A ou de classe B. Puis désérialiser.
hé, hé, je suis un sql junkie trop bien que je suis resté loin de la plus exotique des caractéristiques de xpath... 🙂
Pourriez-vous fournir un bref exemple? Je n'ai pas vraiment l'habitude de xpath. Je me demandais si il vaut la peine de regarder dans. Voulu traiter le XML directement à aussi peu que possible.
OriginalL'auteur Arnshea