2011-01-11 7 views
9

Estoy intentando ejecutar código similar al siguiente:interfaces de Serialización

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Xml.Serialization; 

namespace ConsoleApplication1 
{ 
    [Serializable] 
    [XmlInclude(typeof(List<Class2>))] 
    public class Class1 
    { 
     private IList<Class2> myArray; 

     public IList<Class2> MyArray 
     { 
      get { return myArray; } 
      set { myArray = value; } 
     } 

    } 

    public class Class2 
    { 
     private int myVar; 

     public int MyProperty 
     { 
      get { return myVar; } 
      set { myVar = value; } 
     } 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      XmlSerializer ser = new XmlSerializer(typeof(Class1), new Type[] { typeof(List<Class2>) }); 
      FileStream stream = File.OpenWrite("Data.xml"); 
      ser.Serialize(stream, new List<Class1>()); 
      stream.Close(); 
     } 
    } 
} 

Puede alguien explicarme qué estoy haciendo mal?

me sale un:

No se puede serializar miembro de MiMatriz .. ... porque es una interfaz.

¿No debería el XmlInclude resolver esto?

+0

¿quién dijo algo acerca de deserializar ...? –

Respuesta

13

No. No puede serializar una interfaz. Nunca. Simplemente te lo dije.

Una interfaz no es más que una descripción de un conjunto de comportamientos. No dice nada sobre el contenido de una instancia. En particular, aunque una instancia de una clase que implementa una interfaz debe implementar todos sus miembros, ciertamente tendrá propiedades propias que necesitan ser serializadas.

¿Cómo se deserializaría?

¿Qué clase se usaría para deserializar la interfaz en el otro lado?

+0

¿Alguna solución alternativa? – Shahar

+3

@ Shahar: sí. No hagas eso. Use un tipo concreto, no una interfaz. –

+1

¿Cómo se deserializaría? Como una instancia de la clase que se serializó, igual que List . ¿Qué clase se usaría para deserializar la interfaz del otro lado? Ver la primera respuesta. – jwg

0

Incluyó typeof (Lista < ...>), pero MyArray es del tipo IList < ...> que no es una estructura de datos aparente en sí misma sino más bien un marcador de posición para tomar alguna estructura de datos.

Cambie el tipo de MyArray a un tipo específico (como Lista, por ejemplo) y debería funcionar.

private List<Class2> myArray; 

    public List<Class2> MyArray 
    { 
     get { return myArray; } 
     set { myArray = value; } 
    } 
10

He aquí un solución sombra no probado que tiendo a utilizar, en principio:

private IList<Class2> myArray; 
[XmlIgnore] 
public IList<Class2> MyArray 
{ 
    get { return myArray; } 
    set { myArray = value; } 
} 

[XmlElement("MyArray")] 
public object MyArraySerializable 
{ 
    get { return MyArray; } 
    set { MyArray = value as IList<Class2>; } 
} 

Este serializará lista de todo lo que pueda estar usando como objeto genérico con un atributo tipo que le dirá al deserializer el actual tipo del objeto, por lo que cuando ese objeto se deserializa, se debe convertir a IList<Class2> nuevamente. Recuerde proporcionar cualquier tipo que pueda asumir la interfaz.


veo ninguna razón por la serializador debe ser capaz de serializar tales propiedades. No es como si realmente intentara serializar una interfaz, intenta serializar un objeto que implementa una cierta interfaz (que no es muy diferente de la subclasificación abstracta, algunos lenguajes de programación incluso operan únicamente en interfaces).

Cuando el serializador debe serializar ese objeto se sabe que el objeto implementa la interfaz, todo lo que realmente tiene que hacer es serializarlo y adjuntar el atributo de tipo (como lo hace si serializar clases abstractas o sólo superclases en general).

Ahora el deserializer observa el tipo y puede comprobar si ese objeto, de hecho, implementa la interfaz requerida y luego deserializar a la propiedad respectiva.

+0

Amen. ¡El serializador es estúpido cuando se trata de esto! Gracias por la solución. Es mucho mejor usar interfaces porque la herencia está limitada a una clase base. – toddmo

8

O use el DataContractSerializer en su lugar.

+1

Esta es de hecho la respuesta correcta. http://blogs.msdn.com/b/sowmy/archive/2008/10/04/serializing-internal-types-using-xmlserializer.aspx – l33t