2009-12-01 35 views
6

Tengo una clase derivada que agrega solo métodos a una clase base. ¿Cómo se puede serializar la clase derivada para que coincida con la serialización de la clase base? es decir, el XML serializado de la clase derivada debe verse como:Cómo serializar una clase derivada como su clase base

<BaseClass> 
    ... 
</BaseClass> 

por ejemplo Lo siguiente arrojará una InvalidOperationException "No se esperaba el tipo DerivedClass. Use el atributo XmlInclude o SoapInclude para especificar los tipos que no se conocen estáticamente".

Class BaseClass {} 

Class DerivedClass : BaseClass {} 

DerivedClass derived = new DerivedClass(); 

StreamWriter stream = new StreamWriter("output file path"); 
XmlSerializer serializer = new XmlSerializer(GetType(BaseClass)); 
serializer(stream, derived); 

Respuesta

4

Deberá pasar GetType (DerivedClass) al constructor del serializador, debe coincidir con el tipo del objeto que serializa. Puede usar el atributo <XmlRoot> para cambiar el nombre al elemento raíz. Este código de ejemplo trabajó como se pretende:

using System; 
using System.Xml.Serialization; 
using System.IO; 

class Program { 
    static void Main(string[] args) { 
    var obj = new DerivedClass(); 
    obj.Prop = 42; 
    var xs = new XmlSerializer(typeof(DerivedClass)); 
    var sw = new StringWriter(); 
    xs.Serialize(sw, obj); 
    Console.WriteLine(sw.ToString()); 

    var sr = new StringReader(sw.ToString()); 
    var obj2 = (BaseClass)xs.Deserialize(sr); 
    Console.ReadLine(); 
    } 
} 

public class BaseClass { 
    public int Prop { get; set; } 
} 
[XmlRoot("BaseClass")] 
public class DerivedClass : BaseClass { } 
+0

hace el trabajo, gracias. –

+0

Chicos, estoy teniendo el mismo problema aquí, pero esto no funcionó. Mi clase base se creó a partir de un XSD, por lo que no sé qué poner en [XmlRoot] es el nombre de la clase, o el nombre del elemento raíz de la clase base (debería especificar su espacio de nombres, etc, etc.) – Tejo

+1

¿Existe una solución si solo se conoce la base pero no el tipo derivado? –

0

No lo he probado pero ¿no puedes simplemente echarlo?

serializer(stream, (BaseClass)derived); 

Editar

Además, si usted quiere tener un solo XmlSerialiser que puede hacer frente a múltiples clases derivadas & la clase base entonces necesita especificar todos los tipos en el constructor XmlSerialiser.

XmlSerializer serializer = new XmlSerializer(typeof(BaseClass), new Type[] {typeof(DerivedClass)}); 

Entonces felizmente serializará varios tipos. Sin embargo, también tendrá que usar la solución mencionada anteriormente para obtener el xml de salida para que coincida entre las clases.

+1

No se lanza la misma InvalidOperationException –

0

Después de un poco de google;) Puedo decir que necesitará algo más de código e implementar IXmlSerializable para su clase base, declarando todos los métodos de interfaz virtual y como ellos anulando en tu clase derivada. Aquí hay una muestra topic y similar problem resuelta por la interfaz mencionada.

1

También puede implementar la interfaz ICloneable para la clase base y luego hacer:

var sw = new StringWriter() 

var base = (derived as BaseClass).Clone() 
var serializer = new XmlSerializer(typeof(BaseClass)) 
serializer.Serialize(sw, base) 

Console.WriteLine(sw.ToString()) 

No es un approche perfecto, pero si su clase base es simple, entonces también debería funcionar.

Cuestiones relacionadas