2009-02-22 12 views
46

Este es uno con el que luché durante años, así que pensé en documentar en alguna parte. (Disculpas por hacer y responder una pregunta.)¿Por qué mis propiedades públicas no están serializadas por XmlSerializer?

(C# .net 2.0) Tenía una clase que estaba siendo serializada por XmlSerializer, agregué una nueva propiedad pública, sin embargo, no se incluyó en el XML de salida.

No se menciona en los documentos en ningún lugar que pude encontrar, ¡pero las propiedades públicas deben tener un conjunto y una serialización! Supongo que esto se debe a que supone que si vas a serializar, querrás deserializar desde el mismo archivo, por lo que solo serializará las propiedades que tengan un conjunto y un get.

Respuesta

76

Como se mencionó, la mayoría de las propiedades deben tener un getter y un setter; la principal excepción a esto son las listas, por ejemplo:

private readonly List<Foo> bar = new List<Foo>(); 
public List<Foo> Bar {get { return bar; } } // works fine 

que funcionará bien; sin embargo, si XmlSerializerencuentra un colocador - exige que sea público; lo siguiente será no trabajo:

public List<Foo> Bar {get; private set;} // FAIL 

Otras razones por las que podría no serializa:

  • no es pública con obtener y establecer (o es readonly para un campo)
  • tiene un atributo [DefaultValue], y es con ese valor
  • tiene un método público bool ShouldSerializeFoo() que devolvió falso
  • tiene un público bool FooSpecified {get;set;} propiedad o campo que ha devuelto false
  • se marca [XmlIgnore]
  • se marca [Obsolete]

Cualquiera de estos y hacer que no serializar

+0

Aunque tengo algunas propiedades con solo un get. También están marcados con los atributos XmlArray y XmlArrayItem, así que supongo que es por eso que se salen con la suya. – Rory

+2

En algunos casos, una propiedad que devuelve una colección no necesita un conjunto, pero debe inicializarse en el constructor ... Es el caso para las colecciones sin un constructor público. Pero este comportamiento me parece un poco inconsistente ... –

+0

Nunca me había dado cuenta, gracias Thomas; Investigaré ;-p –

7

El punto sobre captador + setter está hecho en el 3er párrafo en la página "Intro to Xml Serialization". En realidad está en una caja de llamada. No puedo perderlo!

Intro-to-XML Serialization http://www.freeimagehosting.net/uploads/2f04fea2db.png

(quien tiene demasiada diversión con Freeimagehosting.net)

+0

ah, tienes razón de que está ahí, pero está mal que no te lo puedes perder :) – Rory

+0

Leí sobre un estudio una vez, que decía que las personas ignoran los titulares y llaman a los recuadros en los artículos, con más frecuencia de lo que ignoran el texto normal. ?? Contador productivo – Cheeso

+0

@ Cheeso: así es, nunca miro los enlaces patrocinados en los resultados de búsqueda de Google;) –

4

también propiedades que devuelven NULL no se serializado!

+1

¡Ah, pero las propiedades de tipo anulable que devuelven nulo son! Tengo esto aquí público int? Propiedad GroupTypeId que se serializó en este aquí XML - Jon

2

Y si su clase hereda una lista y también tiene sus propios miembros, solo los elementos de la lista se serializan. Los datos presentes en los miembros de su clase no se capturan. ¡Tomó algo de tiempo descubrir esto!

+0

Ah, pero ¿por qué? ¿Alguien sabe? – almcnicoll

5

si no desea implementar Setter adecuados (porque tal vez no son ni queriendo deserializar o cambiar un valor de objetos) que sólo puede utilizar los emisores ficticias como esto set { }, de manera que los XMLSerializer obras, pero no pasa nada si use el Setter ...

iE

public string ID { get { return _item.ID.ToString(); } set { } } 
+2

esto podría ser un problema si un programador junior utiliza esta propiedad setter y piensa que está estableciendo el valor. Todavía prefiero tener "lanzar nueva excepción ..." – user384080

1

Una cosa más que añadir sobre la serialización de las colecciones:

XmlSerializer hace caso omiso de las colecciones de las interfaces!

Y con eso quiero decir ignore. Mientras que obtendrá una excepción para una línea como:

public IFoo Foo { get; set; } 

va no obtener una excepción para:

public ICollection<IFoo> LotsOfFoos { get { return this.fooBackingField; } } 
0

Puede implementar la IXmlSerializer y hacer la serialización de forma manual, y se benefician de la serialización propiedades, y viceversa, deserializarlos usando constructores/asignación de campo privada.

Cuestiones relacionadas