¿Por qué no se serializan las propiedades sin setter?

100

Tengo una clase serializable y una de las propiedades de mi clase genera un Guiden el captador. La propiedad no implementa ningún setter y se ignora durante la serialización. ¿Por qué es eso y siempre tengo que implementar un setter para que mi propiedad sea serializada?

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
    }
}

Intenté implementar un setter vacío y se serializó correctamente.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
        set {}
    }
}

Actualización :

¿Puede señalar cómo debo definir las propiedades cuyos valores nunca cambian o aquellas para las que el valor se genera internamente?

Konstantin Dinev
fuente
1
El segundo ejemplo se serializa correctamente ... ¿Pero qué sucede cuando intentas deserializarlo?
LightStriker
Prueba YAXLib [+ , + ]
Sina Iravanian
3
FYI, el serializador XML ignora [Serializable].
John Saunders
@JohnSaunders No estaba al tanto de eso.
Konstantin Dinev

Respuestas:

59

Es una limitación de XmlSerializerque no serializa propiedades de solo lectura, lo que ha hecho en su segundo ejemplo es esencialmente el truco para que se serialice, sin embargo, es inútil si necesita deserializarlo más tarde.

Alternativamente, puede cambiar al uso de DataContractSerializer , es más flexible.

James
fuente
8
DataContractSerializer también requiere establecedores. Esto es una limitación porque aunque podemos usarlo para un solo tipo de operación, digamos deserialización, pero las declaraciones deben ser para ambos, de lo contrario, el proceso de serialización no sabrá qué hacer con un valor cuando esté tratando de serializar un XML en objetos.
ryadavilli
7
@ryadavilli todo lo marcado como [DataMember]se serializa usando DataContractSerializer(solo lectura o no).
James
1
@James Escribí lo anterior porque obtuve algunos errores de tiempo de compilación cuando intenté lo mismo. Ahora, cuando volví a mi código y eliminé el setter, parece que se está compilando bien. Esto es muy extraño y probablemente una tarea para mí para investigar más sobre esto.
ryadavilli
3
Ahhh finalmente encontré la fuente de mi confusión. No se requiere un establecedor de propiedades para la serialización. Sin embargo, si una propiedad no tiene un establecedor, el XML no se deserializará en un objeto. Allí, los deberes terminaron.
ryadavilli
1
@ryadavilli sí exactamente, es solo una limitación de la XmlSerializerimplementación, se basa en el método de establecimiento público. DataContractSerializeres un poco más inteligente en ese sentido (probablemente usando la reflexión para establecer el campo detrás de escena).
James
10

Consulte " Introducción a la serialización XML " en la documentación de MSDN. Entre otras cosas, dice:

Elementos que se pueden serializar

Los siguientes elementos se pueden serializar mediante la clase XmlSerializer:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

Nota:

Only collections are serialized, not public properties.
XmlElement objects.

XmlNode objects.

DataSet objects.

Además, consulte " Por qué la clase XML-serializable necesita un constructor sin parámetros "


Además, IXmlSerializable

Además de los tipos anteriores que pueden ser serializados por XML Serializer, cualquier tipo que implemente la interfaz IXmlSerializable puede serializarse y deserializarse. En particular, esto significa que los tipos XElement y XDocument se pueden serializar.

Consulte " Interfaz IXmlSerializable ".

John Saunders
fuente
6

Limitación de XMLSerializer: las propiedades sin setter no se pueden serializar.

Pero puede usar DataContractSerializerpara serializar private setter properties:

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Cubas Rohit
fuente
Se supone que la propiedad debe serializarse como un atributo xml (ver publicación original). Su código (atributo DataMember) produce un elemento xml. Hasta donde yo sé, no hay una forma (limpia) de decirle al DataContractSerializer que convierta una propiedad en un atributo y no en un elemento. DataContractSerializer es bueno, pero siempre debe tener en cuenta esta limitación.
sth_Weird
2

si desea tener establecedores privados y que el objeto sea serializable / deserializable, implemente ISerializable y cree un constructor como MyObject (información de SerializationInfo, contexto StreamingContext). Aquí se encuentra un ejemplo .

edamon
fuente
0

Los atributos de serialización se utilizan para serializar y deserializar objetos. XmlSerializer asumirá que no necesita serializar ninguna propiedad que no tenga un setter. Setter se utilizará al deserializar una cadena en un objeto, porque es necesario crear una instancia del objeto y luego se utilizará el setter para completar el valor de la propiedad.

Rui Jarimba
fuente