Qualsiasi buon esempio su come serializzare l'elenco di oggetti generici con classe di base astratta. I campioni con classe base non astratta sono elencati in XML Serialize generic list of serializable objects. La mia classe base è simile a Microsoft.Build.Utilities.TaskXML Serializzare l'elenco generico di oggetti serializzabili con la classe di base astratta
risposta
È spesso utile avere classi astratte con diversi tipi derivati per consentire l'utilizzo di elenchi fortemente tipizzati e di tali.
Ad esempio, è possibile avere una classe DocumentFragment che è astratta e due classi concrete denominate TextDocumentFragment e CommentDocumentFragment (questo esempio di Willis).
Ciò consente la creazione di una proprietà List che può contenere solo oggetti di questi due tipi.
Se si tenta di creare un webservice che restituisce questa lista si ottiene un errore ma questo è facile andare in giro con il codice qui sotto ....
[Serializable()]
[System.Xml.Serialization.XmlInclude(typeof(TextDocumentFragment))]
[System.Xml.Serialization.XmlInclude(typeof(CommentDocumentFragment))]
public abstract class DocumentFragment {
...}
Gli attributi XmlInclude dire alla classe che potrebbe essere serializzato su queste due classi derivate.
Questo genera un attributo nell'elemento DocumentFragment che specifica il tipo effettivo, come di seguito.
<DocumentFragment xsi:type="TextDocumentFragment">
Tutte le proprietà aggiuntive specifiche della classe derivata verranno incluse anche con questo metodo.
Un'altra alternativa è quella di utilizzare il XmlElementAttribute
per spostare l'elenco dei tipi conosciuti alla elenco generico stessa ...
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
public abstract class Animal
{
public int Weight { get; set; }
}
public class Cat : Animal
{
public int FurLength { get; set; }
}
public class Fish : Animal
{
public int ScalesCount { get; set; }
}
public class AnimalFarm
{
[XmlElement(typeof(Cat))]
[XmlElement(typeof(Fish))]
public List<Animal> Animals { get; set; }
public AnimalFarm()
{
Animals = new List<Animal>();
}
}
public class Program
{
public static void Main()
{
AnimalFarm animalFarm = new AnimalFarm();
animalFarm.Animals.Add(new Cat() { Weight = 4000, FurLength = 3 });
animalFarm.Animals.Add(new Fish() { Weight = 200, ScalesCount = 99 });
XmlSerializer serializer = new XmlSerializer(typeof(AnimalFarm));
serializer.Serialize(Console.Out, animalFarm);
}
}
... che sarà anche tradursi in un output XML più bello (senza il brutto Attributo xsi:type
) ...
<?xml version="1.0" encoding="ibm850"?>
<AnimalFarm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Cat>
<Weight>4000</Weight>
<FurLength>3</FurLength>
</Cat>
<Fish>
<Weight>200</Weight>
<ScalesCount>99</ScalesCount>
</Fish>
</AnimalFarm>
se non si desidera mantenere l'elemento Animals, è possibile utilizzare invece XmlArrayItemAttribute. – Console
Accetto con @Dmitry. È possibile trovare una risposta alternativa in Serializzazione senza XmlIncludere http://stackoverflow.com/questions/370291/serializing-without-xmlinclude – walter