Por que as propriedades sem um setter não são serializadas

101

Eu tenho uma classe serializável e uma das propriedades da minha classe gera um Guidno getter. A propriedade não implementa nenhum setter e é ignorada durante a serialização. Por que é isso e sempre tenho que implementar um setter para que minha propriedade seja serializada.

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

Tentei implementar um setter vazio e ele foi serializado corretamente.

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

Atualização :

Você pode apontar como devo definir propriedades cujos valores nunca mudam ou aqueles para os quais o valor é gerado internamente?

Konstantin Dinev
fonte
1
O segundo exemplo serializa corretamente ... Mas o que acontece quando você tenta desserializar?
LightStriker de
Experimente YAXLib [+ , + ]
Sina Iravanian de
3
FYI, o XML Serializer ignora [Serializable].
John Saunders de
@JohnSaunders Eu não sabia disso.
Konstantin Dinev

Respostas:

60

É uma limitação de XmlSerializernão serializar propriedades somente leitura, o que você fez em seu segundo exemplo é essencialmente o hack para fazê-lo serializar, no entanto, é inútil se você precisar desserializar mais tarde.

Alternativamente, você pode mudar para o DataContractSerializer , é mais flexível.

James
fonte
8
DataContractSerializer também requer setters. Esta é uma limitação porque, embora possamos usá-lo para apenas um tipo de operação, digamos desserialização, mas as declarações precisam ser para ambos, caso contrário, o processo de serialização não saberá o que fazer com um valor quando ele está tentando serializar um XML em objetos.
ryadavilli
7
@ryadavilli qualquer coisa marcada como [DataMember]serializada usando DataContractSerializer(somente leitura ou não).
James
1
@James Eu escrevi acima porque recebi alguns erros de compilação quando tentei fazer o mesmo. Agora, quando voltei ao meu código e removi o setter, parece que está compilando bem. Isso é muito estranho e provavelmente um dever de casa para eu pesquisar mais sobre isso.
ryadavilli
3
Ahhh finalmente encontrou a fonte da minha confusão. Um configurador de propriedade não é necessário para serialização. No entanto, se uma propriedade não tiver um configurador, o XML não será desserializado para um objeto. Pronto, lição de casa terminada.
ryadavilli
1
@ryadavilli sim exatamente, é apenas uma limitação da XmlSerializerimplementação, ele depende do método setter público. DataContractSerializeré um pouco mais inteligente nesse sentido (provavelmente usando reflexão para definir o campo nos bastidores).
James
10

Consulte " Introdução à serialização de XML " na documentação do MSDN. Entre outras coisas, diz:

Itens que podem ser serializados

Os seguintes itens podem ser serializados usando a classe 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.

Além disso, consulte " Por que a classe XML-Serializable precisa de um construtor sem parâmetros "


Além disso, IXmlSerializable

Além dos tipos acima, que podem ser serializados pelo XML Serializer, qualquer tipo que implemente a interface IXmlSerializable pode ser serializado e desserializado. Em particular, isso significa que os tipos XElement e XDocument podem ser serializados.

Consulte " Interface IXmlSerializable ".

John Saunders
fonte
6

Limitação de XMLSerializer- Propriedades sem configurador não podem ser serializadas.

Mas você pode usar DataContractSerializerpara serializar private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Rohit Vats
fonte
A propriedade deve ser serializada como um atributo xml (veja a postagem original). Seu código (atributo DataMember) produz um elemento xml. Pelo que eu sei, não há uma maneira (limpa) de dizer ao DataContractSerializer para transformar uma propriedade em um atributo e não em um elemento. DataContractSerializer é bom, mas você sempre deve manter essa limitação em mente.
sth_Weird de
2

se quiser ter configuradores privados e o objeto ser serializável / desserializável, implemente ISerializable e crie um construtor como MyObject (informações de SerializationInfo, contexto de StreamingContext). Um exemplo é encontrado aqui .

edamon
fonte
0

Os atributos de serialização são usados ​​para serializar e desserializar objetos. XmlSerializer assumirá que você não precisa serializar qualquer propriedade que não tenha um setter. O setter será usado ao desserializar uma string em um objeto, porque uma instância do objeto precisa ser criada e, em seguida, o setter será usado para preencher o valor da propriedade.

Rui Jarimba
fonte