2010-01-26 18 views
5

Tengo una clase con algunas colecciones en ellas, y me gustaría serializar las instancias de esta clase a XML sin tener que inicializar las colecciones para que estén vacías, y sin tener que implementar IXmlSerializable. No me importa si crea elementos vacíos, o no crea los elementos en absoluto. Solo que funciona sin tener que inicializar una colección para cada propiedad basada en colección.Serv. XML .NET y colecciones nulas

He visto todos los atributos XML con los que puedo decorar las propiedades, y no he tenido éxito con esto. Esto parece una cosa simple de hacer que puede tener un elemento o simplemente no tener ninguno. Luego, cuando se deserialice, simplemente los dejará nulos o los ignorará.

Aquí hay una versión simple de una clase para usar para resolver este problema. Al usar esto y los valores predeterminados, se obtiene una excepción "Referencia de objeto no establecida en una instancia de un objeto" debido a que las colecciones son nulas;

public class MyClass 
{ 
    public string Name { get; set; } 
    public bool IsAlive { get; set; } 
    public List<Car> Cars { get; set; } 
    public List<Home> Homes { get; set; } 
    public List<Pet> Pets { get; set; } 

    public void ToXmlFile(string fileName) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); 
     TextWriter writer = new StreamWriter(fileName); 
     serializer.Serialize(writer, this); 
     writer.Close(); 
    } 
} 

EDITAR Gracias por la ayuda a los hombres, resulta que el problema estaba en mi método GetHashCode que no manejan la hipótesis nula correctamente. Una vez que arreglé esto, todo estuvo bien. Marqué el primero para responder como correcto. Perdón por el Red Herring, pero trabajando con ustedes ayudaron.

+0

¿Y cuál es el problema? Eso debería funcionar (serializar y deserializar al menos); ¿Qué comportamiento es lo que no te gusta? –

+0

No pude reproducir la excepción que dice obtener. Pude serializar y deserializar una instancia de tu MyClass exacta como la diste. Tal vez hay algo más pasando? –

+0

@Brian Sí, algo más estaba pasando, gracias por toda la ayuda rápida y porque no era el código XML en sí. :) –

Respuesta

5

No necesita inicializar colecciones para serializar la clase a XML. He aquí un programa sencillo para demostrar:

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyClass c = new MyClass() { Name = "Test", IsAlive = true }; 
     XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      serializer.Serialize(ms, c); 
      Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 
     } 
     Console.ReadLine(); 
    } 
} 

Esto imprimirá el siguiente resultado:

<?xml version="1.0"?> 
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Name>Test</Name> 
    <IsAlive>true</IsAlive> 
</MyClass> 

En otras palabras, null propiedades de la colección se comportan de la misma manera que cualquier otra null propiedad - no consiguen serializado en absoluto (a menos que cambie el valor predeterminado, que no tengo).

+0

Actualicé la pregunta, obtengo y la excepción "Referencia de objeto no establecida en una instancia de un objeto" al hacer esto. Estoy haciendo esto en un archivo usando StreamWriter y haciendo desde un método ToXmlFile en la clase misma que usa "this" palabra clave para referenciar qué objeto serializar. Las clases definidas para las listas genéricas son simples con solo primitivas o enumeraciones en ellas. Lo que dices es cómo espero que funcione, pero no es así. Actualizaré la clase con el código usado para la serialización también. –

+0

Gracias, el problema estaba en otro lugar, como Brian eludió en su comentario sobre la pregunta. –

0

Puede serializar esto sin problema, solo debe enviar los tipos de automóvil, hogar y mascota al serializar en el parámetro extraTypes.

0

Menciona una excepción durante (de) serialización; lo que tienes debe funcionar bien (al menos, según cómo defines la pregunta).Me pregunto si realmente tiene:

public class MyClass 
{ 
    public string Name { get; set; } 
    public bool IsAlive { get; set; } 
    public List<Car> Cars { get; private set; } 
    public List<Home> Homes { get; private set; } 
    public List<Pet> Pets { get; private set; } 
} 

(no es raro que no quieren un regulador público)

Bueno, XmlSerializer es exigente con esto; usted necesita un organismo público o (como alguien señaló recientemente) no setter; por ejemplo:

public class MyClass 
{ 
    public string Name { get; set; } 
    public bool IsAlive { get; set; } 
    private readonly List<Car> cars = new List<Car>(); 
    public List<Car> Cars { get { return cars; } } 
    private readonly List<Home> homes = new List<Home>(); 
    public List<Home> Homes { get { return homes; } } 
    private readonly List<Pet> pets = new List<Pet>(); 
    public List<Pet> Pets { get { return pets; } } 
} 
0

Creo que ajustar el tipo de retorno del método XMLSerialisation a un bool le permitirá manejar los errores de un modo más seguro en comparación con el método actual:

public bool ToXmlFile(string fileName) 
{ 
    if(fileName != "") 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); 
     TextWriter writer = new StreamWriter(fileName); 
     serializer.Serialize(writer, this); 
     writer.Close(); 
     return true; 
    } 
    return false; 
} 

Qué a continuación, se puede utilizar de esta manera:

if(ToXMLFile) 
{ 
    MessageBox.Show("Save Succesful"); 
} 
else 
(
    MessageBox.Show("Save unsuccesful"); 
) 

Esto es simplemente un ejemplo crudo sin embargo he utilizado un método similar en mis propias aplicaciones cuando loa ding o guardar datos y funciona bien, también es un buen indicador visual para el usuario final.

Cuestiones relacionadas