2010-08-28 15 views
5

Esta es mi primera pregunta sobre Stack Overflow. Disculpas por adelantado si no hago las cosas bien mientras estoy aprendiendo cómo funcionan las cosas aquí.C# XML Serializer no almacenará un atributo

Aquí está mi código:

public void TestSerialize() 
{ 
    ShoppingBag _shoppingBag = new ShoppingBag(); 
    Fruits _fruits = new Fruits(); 
    _fruits.testAttribute = "foo"; 

    Fruit[] fruit = new Fruit[2]; 
    fruit[0] = new Fruit("pineapple"); 
    fruit[1]= new Fruit("kiwi"); 

    _fruits.AddRange(fruit); 

    _shoppingBag.Items = _fruits; 

    Serialize<ShoppingBag>(_shoppingBag, @"C:\temp\shopping.xml"); 
} 

public static void Serialize<T>(T objectToSerialize, string filePath) where T : class 
{ 
    XmlSerializer serializer = new XmlSerializer(typeof(T)); 

    using (StreamWriter writer = new StreamWriter(filePath)) 
    { 
     serializer.Serialize(writer, objectToSerialize); 
    } 
} 

[Serializable] 
public class ShoppingBag 
{ 
    private Fruits _items; 

    public Fruits Items 
    { 
     get { return _items; } 
     set {_items = value; } 
    } 
} 

public class Fruits : List<Fruit> 
{ 
    public string testAttribute { get; set; } 
} 

[Serializable] 
public class Fruit 
{ 
    public Fruit() { } 

    public Fruit(string value) 
    { 
     Name = value; 
    } 

    [XmlAttribute("name")] 
    public string Name { get; set; } 
} 

Produce este XML:

<?xml version="1.0" encoding="utf-8" ?> 
<ShoppingBag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Items> 
    <Fruit name="pineapple" /> 
    <Fruit name="kiwi" /> 
    </Items> 
</ShoppingBag> 

No entiendo por qué no estoy recibiendo <Items testAttribute="foo">

Por favor, ¿alguien puede decir lo que yo ¿Necesito agregar a mi código para que el serializador escriba este atributo?

Gracias,

+3

@ martin-65, bienvenido a SO. Esta es una muy buena pregunta y debería servir como un ejemplo de cómo hacer preguntas incluso a usuarios más avezados en este sitio. Ha formateado correctamente su código, proporcionó un ejemplo de trabajo completo (que es fácil de reproducir en cualquier PC) aislando el problema, proporcionó el resultado del fragmento y explicó cuál es el resultado deseado. –

+0

Gracias por la bienvenida y el aliento. – MartinC

Respuesta

0

Desafortunadamente, al serializar una colección, el XmlSerializer no tiene en cuenta las propiedades adicionales de esa colección. Solo considera a los miembros que implementan ICollection<T>. Si desea serializar atributos adicionales, debe envolver la colección en otra clase que no sea una colección en sí misma.

2

Se necesitan una clase intermediaria ahí:

class Program 
{ 
    static void Main() 
    { 
     var shoppingBag = new ShoppingBag 
     { 
      Items = new ShoppingBagItems 
      { 
       Fruits = new List<Fruit>(new[] { 
        new Fruit { Name = "pineapple" }, 
        new Fruit { Name = "kiwi" }, 
       }), 
       TestAttribute = "foo" 
      } 
     }; 
     var serializer = new XmlSerializer(typeof(ShoppingBag)); 
     serializer.Serialize(Console.Out, shoppingBag); 
    } 
} 

public class ShoppingBag 
{ 
    public ShoppingBagItems Items { get; set; } 
} 

public class ShoppingBagItems 
{ 
    [XmlElement("Fruit")] 
    public List<Fruit> Fruits { get; set; } 

    [XmlAttribute("testAttribute")] 
    public string TestAttribute { get; set; } 
} 

public class Fruit 
{ 
    [XmlAttribute("name")] 
    public string Name { get; set; } 
} 

También tenga en cuenta que no es necesario para decorar sus clases con el atributo [Serializable] ya que se utiliza sólo para la serialización binaria. Otra observación es que no necesita derivar del List<T>, simplemente úselo como una propiedad.

+0

Gracias por su respuesta, Darin. No entiendo a qué te refieres cuando dices que necesito una clase de intermediario. Has usado 3 clases (ShoppingBag, ShoppingBagItems, Fruit) como lo hice (ShoppingBag, Fruits, Fruit). Gracias por la sugerencia de no necesitar el atributo '[Serializable]'. Su punto sobre 'List ' es el meollo de mi problema. Si cambio mi código original para no derivar 'Fruits' from' List ', entonces funciona bien ... – MartinC

+0

Sin embargo, de vuelta al trabajo me solicitaron que me derivara de la Lista para que cuando deserializara el XML I puede usar foreach fácilmente en mis clases (sin tener que implementar IEnumerable). (Mi XML tiene 7 niveles de objetos, no estoy realizando la serialización, solo la deserialización. Lo que comenzó esto fue que no pude leer un atributo en el nivel 4 y entonces pensé que si podía serializarlo correctamente, entonces debería estar capaz de deserializarlo). Entonces, ¿por qué derivar de 'List ' detener el atributo que se está escribiendo? y ¿cómo puedo ambos derivar de la lista y escribir/leer ese atributo? – MartinC

Cuestiones relacionadas