2009-11-10 14 views
11

tengo estructura como esta:NET serialización XML y la herencia

public interface A 
{ 
    public void method(); 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

List<A> list; 

lista contiene objetos de tipo B y C también tienen algunos campos que me gustaría mantener, puedo ahora serializar, deserializar vuelta y obtener las instancias de objeto adecuadas? Preferiblemente a XML

EDIT:

¿Hay alguna manera sencilla para serializar esta lista que contiene las interfaces y, a continuación, deserializar nuevo a casos B y C?

Respuesta

4

Eres ma y prueba usando DataContractSerializer:

public interface A 
{ 
} 

public class B : A 
{ 
} 

public class C : A 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<A> list = new List<A>(new A[] { new B(), new C() }); 
     var serializer = new DataContractSerializer(
      list.GetType(), new[] { typeof(B), typeof(C) }); 

     var sb = new StringBuilder(); 
     using (var stringWriter = new StringWriter(sb)) 
     using (var writer = XmlWriter.Create(stringWriter)) 
     { 
      serializer.WriteObject(writer, list); 
     } 

     using (var stringReader = new StringReader(sb.ToString())) 
     using (var reader = XmlReader.Create(stringReader)) 
     { 
      list = (List<A>)serializer.ReadObject(reader); 
     } 

    } 
} 
4

Sí, pero tiene que jugar con los atributos XmlElement, XmlRoot y XmlArray. Cada tipo necesita su propio nombre de elemento.

EDITAR: Algunos ejemplos de código. Todas las clases se derivan de una clase base común.

Aquí es un ejemplo de código:

[XmlRoot(ElementName="Root")] 
public sealed class SomeObject 
{ 

    private BaseObject _Object; 

    [XmlElement(Type=typeof(App.Projekte.Projekt), ElementName="Projekt")] 
    [XmlElement(Type=typeof(App.Projekte.Task), ElementName="Task")] 
    [XmlElement(Type=typeof(App.Projekte.Mitarbeiter), ElementName="Mitarbeiter")] 
    public BaseObject Object 
    { 
     get 
     { 
      return _Object; 
     } 
     set 
     { 
      _Object = value; 
     } 
    } 
} 

EDIT: Retire la serialización Atributo ya que no es necesario (pero se necesita en mi proyecto en el que el código es de)

+1

No necesita '[Serializable]'. No es utilizado por Serialización XML. –

6

Suponiendo que está usando el incorporado en la serialización XML .NET usted debe echar un vistazo a los siguientes atributos:

System.Xml.Serialization.XmlIncludeAttribute 

te permite indicar al serializador para incluir otros tipos al serializar/de serialización.

Agregar nuevos tipos a la lista y no actualizar los metadatos de serialización es una fuente común de errores, asegúrese de tener una cobertura de prueba adecuada.

0

Para su caso, hacer una clase abstracta que implementa la interfaz como:

abstract class Abs : A 

y luego derivan sus clases de Abs

public class B : Abs 
public class C : Abs 

y Lista lista;

ahora usa XmlIncludeAttribute para agregar tus tipos a la matriz de tipos de XmlSerializer.

5

Utilizaría una clase abstracta en lugar de una interfaz (ya que no se puede serializar un tipo de interfaz), luego, en lugar de codificar el tipo con el atributo XmlInclude, agregaría los tipos conocidos al XmlSerializer en el Serial y Deserialize métodos de esta manera:

string listXml = Serialize<List<A>>(ListA, new Type[] { typeof(B), typeof(C) }); 

    List<IA> NewList = Deserialize<List<A>>(listXml, new Type[] { typeof(B), typeof(C) }); 

    private static T Deserialize<T>(string Xml, Type[] KnownTypes) 
    { 
     XmlSerializer xs = new XmlSerializer(typeof(T),KnownTypes); 

     StringReader sr = new StringReader(Xml); 
     return (T)xs.Deserialize(sr); 
    } 

    private static string Serialize<T>(Object obj, Type[] KnownTypes) 
    { 
     StringBuilder sb = new StringBuilder(); 
     using (StringWriter sw = new StringWriter(sb)) 
     { 
      XmlSerializer xs = new XmlSerializer(typeof(T), KnownTypes); 

      xs.Serialize(sw, obj); 
     } 
     return sb.ToString(); 
    } 
0

XmlSerializer no funciona con interfaces.Por lo que puede:

interfaz Convertir a clase abstracta y luego usar XmlIncludeAttribute para ello o proporcionar KnownTypes a XmlSerializer

o

Implementar IXmlSerializable para el tipo de matriz

o

Considere el uso DataContractSerializer de .NET 3.0

Cuestiones relacionadas