2012-03-06 8 views
10

Estoy notando un comportamiento extraño con el XmlSerializer y listas genéricas (específicamente List<int>). Me preguntaba si alguien ha visto esto antes o si sabe lo que está pasando. Parece que la serialización funciona bien, pero la deserialización quiere agregar elementos adicionales a la lista. El código a continuación demuestra el problema.Deserializando la lista <int> con XmlSerializer causando elementos extra

clase Serializable: Código

public class ListTest 
{ 
    public int[] Array { get; set; } 
    public List<int> List { get; set; } 

    public ListTest() 
    { 
     Array = new[] {1, 2, 3, 4}; 
     List = new List<int>(Array); 
    } 
} 

prueba: salida

ListTest listTest = new ListTest(); 
Debug.WriteLine("Initial Array: {0}", (object)String.Join(", ", listTest.Array)); 
Debug.WriteLine("Initial List: {0}", (object)String.Join(", ", listTest.List)); 

XmlSerializer serializer = new XmlSerializer(typeof(ListTest)); 
StringBuilder xml = new StringBuilder(); 
using(TextWriter writer = new StringWriter(xml)) 
{ 
    serializer.Serialize(writer, listTest); 
} 

Debug.WriteLine("XML: {0}", (object)xml.ToString()); 

using(TextReader reader = new StringReader(xml.ToString())) 
{ 
    listTest = (ListTest) serializer.Deserialize(reader); 
} 

Debug.WriteLine("Deserialized Array: {0}", (object)String.Join(", ", listTest.Array)); 
Debug.WriteLine("Deserialized List: {0}", (object)String.Join(", ", listTest.List)); 

Depuración:

Initial Array: 1, 2, 3, 4 
Initial List: 1, 2, 3, 4 

XML:

<?xml version="1.0" encoding="utf-16"?> 
<ListTest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Array> 
    <int>1</int> 
    <int>2</int> 
    <int>3</int> 
    <int>4</int> 
    </Array> 
    <List> 
    <int>1</int> 
    <int>2</int> 
    <int>3</int> 
    <int>4</int> 
    </List> 
</ListTest> 
Deserialized Array: 1, 2, 3, 4 
Deserialized List: 1, 2, 3, 4, 1, 2, 3, 4 

Observe que tanto el conjunto como la lista parecen haberse serializado en XML correctamente, pero en la deserialización, la matriz sale correcta pero la lista vuelve con un conjunto duplicado de elementos. ¿Algunas ideas?

+1

Gracias por las respuestas - como he mencionado en un comentario más abajo, no me di cuenta del deserializer fue capaz de mutar el estado de los miembros durante la deserialización (en la mayoría de los casos creo que sólo establece nuevos valores, ¿verdad?) ¿Es la lista la única clase con la que puede hacer esto? ¿Hay alguna referencia que indique qué clases puede mutar el deserializador? – daveaglick

Respuesta

7

Sucede porque está inicializando la Lista en el constructor. Cuando vaya a deserializar, se crea un nuevo ListTest y luego rellena el objeto del estado.

Piense en el flujo de trabajo como éste

  1. Crear un nuevo ListTest
  2. Ejecutar el Constructor (añadir 1,2,3,4)
  3. deserializar el estado xml, y añadir 1,2, 3,4 a la lista

Una solución simple sería iniciar el objeto fuera del alcance del constructor.

public class ListTest 
{ 
    public int[] Array { get; set; } 
    public List<int> List { get; set; } 

    public ListTest() 
    { 

    } 

    public void Init() 
    { 
     Array = new[] { 1, 2, 3, 4 }; 
     List = new List<int>(Array); 
    } 
} 

ListTest listTest = new ListTest(); 
listTest.Init(); //manually call this to do the initial seed 
3

El problema es que está definiendo el original 1,2,3,4 en la Lista en el constructor predeterminado. Su deserializador se está agregando a la lista, no definiéndola.

+3

Gracias, mover la inicialización del constructor solucionó el problema. No entendí cómo funciona el deserializador. No me di cuenta de que muta los objetos existentes, pensé que siempre usaba el acceso de conjunto para escribir nuevas instancias de niños en el objeto recién construido (en cuyo caso la lista creada en el constructor simplemente se habría olvidado). Aprendes algo cada día. – daveaglick

Cuestiones relacionadas