Je convertis ma sérialisation XML de travail afin que les classes de modèles héritent des classes de base abstraites (pour permettre l'utilisation future de différents formats de série). Mon serial-as fonctionne correctement, mais lorsque je passe à l'utilisation de modèles dérivés d'une classe de base, j'obtiens toutes sortes d'exceptions, donc je ne sais pas comment procéder.Comment utiliser la classe dérivée pour la sérialisation XML?
Ma classe de base de classe est:
namespace Data
{
public abstract class Configuration
{
public abstract string Schema { get; set; }
public abstract Command[] Commands { get; set; }
}
public abstract class Command
{
public abstract string Name { get; set; }
}
}
Ma classe concrète dérivée (la classe qui fonctionne très bien avant qu'il ne soit dérivé) est alors dans un espace de nom de l'enfant:
namespace Data.Xml
{
[Serializable()]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class Configuration : Data.Configuration
{
[XmlAttribute("noNamespaceSchemaLocation",
Namespace = System.Xml.Schema.XmlSchema.InstanceNamespace)]
public override string Schema { get; set; }
[XmlArrayItem("Command", IsNullable = false)]
public override Data.Command[] Commands { get; set; }
}
[Serializable()]
public class Command : Data.Command
{
public override string Name { get; set; }
}
}
J'appelle le sérialiseur dans cet espace de noms enfant comme suit:
public override Data.Configuration DeserializeConfig(StreamReader config)
{
var cs = new XmlSerializer(typeof(Configuration),
new Type[] { typeof(Command) });
return (Configuration)ConfigSerializer.Deserialize(ConfigStreamReader);
}
public override string SerializeConfig(Data.Configuration c, Encoding encoding)
{
string Output = null;
var Stream = new MemoryStream();
using (var Writer = new XmlTextWriter(Stream, encoding))
{
Writer.Formatting = Formatting.Indented;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xsi", XmlSchema.InstanceNamespace);
(new XmlSerializer(typeof(Configuration))).Serialize(Writer, c, ns);
Output = encoding.GetString(Stream.ToArray());
}
Stream.Dispose();
return Output;
}
Le XML résultant devrait ressembler :
<?xml version="1.0" encoding="utf-8"?>
<Configuration
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="SomeSchema.xsd">
<Commands>
<Command>
<Name>SomeNameValue</Name>
</Command>
</Commands>
</Configuration>
Je vois l'exception suivante lors d'une tentative d'instancier le sérialiseur (première ligne dans la méthode DeserializeConfig()
ci-dessus):
InvalidOperationException: Types 'Data.Command' et « Data.Xml.Command 'les deux utilisent le nom de type XML,' Command ', à partir de l'espace de noms' '. Utilisez les attributs XML pour spécifier un nom XML unique et/ou un espace de noms pour le type.
Je ne suis pas vraiment sûr pourquoi le sérialiseur tente de créer quelque chose à partir de la classe de base, que les noms sont les mêmes, que ce genre de l'idée de dérivation et les espaces de noms, etc ... Comment puis-je bien marquer ceci avec des attributs pour l'avoir de/sérialiser correctement?
Pour votre information: J'ai vu plusieurs questions déjà à ce sujet, mais toutes les réponses semblaient assez spécifiques aux exigences de Askers que je ne pouvais pas travailler sur la façon d'appliquer les informations à ce, en apparence simple, scénario. J'ai découvert comment passer les types inclus dans le sérialiseur à l'instanciation au lieu d'avoir à annoter la classe de base. J'ai donc supprimé cette partie de ma question et mis à jour le code. Ceci surpasse la suggestion de bruno et ma réponse (bien que la question suggérée ne s'applique toujours pas).
Mise à jour: J'ai essayé de séparer les noms XML namespaces en ajoutant la classe dérivée à un espace de noms (par exemple l'ajout [XmlElement(Namespace = "http://www.foo.com/data/xml")]
à chaque propriété dans la classe dérivée), mais cela n'a fait aucune différence que le sérialiseur semble encore « voir "à la fois la base et la classe dérivée ensemble et pense donc qu'ils sont tous les deux dans cet espace de noms.
est-ce une question de double https://stackoverflow.com/questions/3326481/c -sharp-xml-serialization-of-classes-dérivées? –
@ bruno.almeida, Non, j'ai déjà l'attribut 'XmlInclude' appliqué. – Toby
Ce sont vos noms de classe qui perturbent le compilateur. La bibliothèque Net a System.Net.Data et System.Net.Xml. Les noms de classe que vous utilisez dupliquent les noms Net Library. Donc changez les noms ou utilisez des noms complets comme MyProject.Data.Xml. – jdweng