2012-02-12 8 views
6

Cualquier buena muestra sobre cómo serializar la lista de objetos genéricos con clase base abstracta. Las muestras con clase base no abstracta se enumeran en XML Serialize generic list of serializable objects. Mi clase base es similar a Microsoft.Build.Utilities.TaskXML Serializar lista genérica de objetos serializables con clase base abstracta

+0

De acuerdo con @Dmitry. Se puede encontrar una respuesta alternativa en Serializar sin XmlInclude http://stackoverflow.com/questions/370291/serializing-without-xmlinclude – walter

Respuesta

4

A menudo es útil tener clases abstractas con varios tipos derivados para permitir el uso de listas fuertemente tipadas y similares.

Por ejemplo, puede tener una clase DocumentFragment que es abstracta y dos clases concretas llamadas TextDocumentFragment y CommentDocumentFragment (este ejemplo de Willis).

Esto permite la creación de una propiedad de Lista que puede contener solo objetos de esos dos tipos.

Si se intenta crear un servicio web que devuelve esta lista se produce un error, pero esto es fácil de recorrer con el código de abajo ....

[Serializable()] 
[System.Xml.Serialization.XmlInclude(typeof(TextDocumentFragment))] 
[System.Xml.Serialization.XmlInclude(typeof(CommentDocumentFragment))] 
public abstract class DocumentFragment { 
...} 

Los atributos XmlInclude decir a la clase que podría ser serializado a esas dos clases derivadas.

Esto genera un atributo en el elemento DocumentFragment que especifica el tipo real, como se muestra a continuación.

<DocumentFragment xsi:type="TextDocumentFragment"> 

Cualquier propiedad adicional específica para la clase derivada también se incluirá con este método.

11

Otra alternativa es utilizar el XmlElementAttribute para mover la lista de tipos conocidos en la lista genérica en sí ...

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); 
    } 
} 

... que también dará lugar a una salida XML mejor aspecto (sin la fea xsi:type atributo) ...

<?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> 
+0

si desea mantener el elemento Animals, puede usar XmlArrayItemAttribute en su lugar. – Console

Cuestiones relacionadas