Pourquoi les propriétés sans setter ne sont-elles pas sérialisées

101

J'ai une classe sérialisable et l'une des propriétés de ma classe génère un Guiddans le getter. La propriété n'implémente aucun setter et est ignorée lors de la sérialisation. Pourquoi et dois-je toujours implémenter un setter pour que ma propriété soit sérialisée.

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

J'ai essayé d'implémenter un setter vide et il a été sérialisé correctement.

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

Mise à jour :

Pouvez-vous indiquer comment définir les propriétés dont les valeurs ne changent jamais ou celles dont la valeur est générée en interne?

Konstantin Dinev
la source
1
Le deuxième exemple sérialise correctement ... Mais que se passe-t-il lorsque vous essayez de le désérialiser?
LightStriker
Essayez YAXLib [+ , + ]
Sina Iravanian
3
FYI, le sérialiseur XML ignore [Serializable].
John Saunders
@JohnSaunders Je n'étais pas au courant de cela.
Konstantin Dinev

Réponses:

60

C'est une limitation du fait XmlSerializerqu'il ne sérialise pas les propriétés en lecture seule, ce que vous avez fait dans votre deuxième exemple est essentiellement le hack pour le faire sérialiser, cependant, il est inutile si vous en avez besoin pour désérialiser plus tard.

Vous pouvez également passer à l'utilisation de DataContractSerializer , c'est plus flexible.

James
la source
8
DataContractSerializer nécessite également des setters. Ceci est une limitation car même si nous pouvons l'utiliser pour un seul type d'opération, disons la désérialisation, mais les déclarations doivent être pour les deux sinon, le processus de sérialisation ne saura pas quoi faire avec une valeur quand il essaie de sérialiser un XML en objets.
ryadavilli
7
@ryadavilli tout ce qui est marqué comme [DataMember]est sérialisé en utilisant DataContractSerializer(en lecture seule ou non).
James
1
@James J'ai écrit ce qui précède parce que j'ai eu des erreurs de compilation lorsque j'ai essayé la même chose. Maintenant, quand je suis revenu à mon code et que j'ai supprimé le setter, il semble bien se compiler. C'est très étrange et probablement un devoir pour moi de rechercher davantage à ce sujet.
ryadavilli
3
Ahhh a finalement trouvé la source de ma confusion. Un dispositif de définition de propriété n'est pas requis pour la sérialisation. Cependant, si une propriété n'a pas de setter, le XML ne sera pas désérialisé en un objet. Là, les devoirs sont terminés.
ryadavilli
1
@ryadavilli ouais exactement, c'est juste une limitation de l' XmlSerializerimplémentation, ça s'appuie sur la méthode du setter public. DataContractSerializerest un peu plus intelligent dans ce sens (en utilisant probablement la réflexion pour définir le champ dans les coulisses).
James
10

Consultez « Présentation de la sérialisation XML » dans la documentation MSDN. Entre autres choses, il dit:

Articles pouvant être sérialisés

Les éléments suivants peuvent être sérialisés à l'aide de la classe XmlSerializer:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

Remarque:

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

XmlNode objects.

DataSet objects.

Consultez également " Pourquoi la classe XML-Serializable a besoin d'un constructeur sans paramètre "


Aussi, IXmlSerializable

En plus des types ci-dessus qui peuvent être sérialisés par le sérialiseur XML, tout type qui implémente l'interface IXmlSerializable peut être sérialisé et désérialisé. En particulier, cela signifie que les types XElement et XDocument peuvent être sérialisés.

Voir « Interface IXmlSerializable ».

John Saunders
la source
6

Limitation de XMLSerializer- Les propriétés sans setter ne peuvent pas être sérialisées.

Mais vous pouvez utiliser DataContractSerializerpour sérialiser private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Cuves Rohit
la source
La propriété est censée être sérialisée en tant qu'attribut xml (voir l'article original). Votre code (attribut DataMember) produit un élément xml. Pour autant que je sache, il n'existe aucun moyen (propre) de dire au DataContractSerializer de transformer une propriété en attribut et non en élément. DataContractSerializer est bien, mais vous devez toujours garder cette limitation à l'esprit.
sth_Weird
2

si vous voulez avoir des setters privés et que l'objet soit sérialisable / désérialisable, implémentez ISerializable et créez un constructeur comme MyObject (SerializationInfo info, contexte StreamingContext). Un exemple se trouve ici .

Edamon
la source
0

Les attributs de sérialisation sont utilisés pour sérialiser et désérialiser des objets. XmlSerializer supposera que vous n'avez pas besoin de sérialiser une propriété qui n'a pas de setter. Setter sera utilisé lors de la désérialisation d'une chaîne dans un objet, car une instance de l'objet doit être créée, puis le setter sera utilisé pour remplir la valeur de la propriété.

Rui Jarimba
la source