J'essaie de sérialiser un objet en XML comportant un certain nombre de propriétés, dont certaines sont en lecture seule.
public Guid Id { get; private set; }
J'ai marqué la classe [Serializable] et j'ai implémenté l'interface ISerializable.
Vous trouverez ci-dessous le code que j'utilise pour sérialiser mon objet.
public void SaveMyObject(MyObject obj)
{
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
TextWriter tw = new StreamWriter(_location);
serializer.Serialize(tw, obj);
tw.Close();
}
Malheureusement, ce message tombe sur la première ligne.
InvalidOperationException n'a pas été gérée: Impossible de générer une classe temporaire (résultat = 1) . erreur CS0200: Impossible d'affecter une propriété ou un indexeur 'MyObject.Id' - lecture seule
Si je mets la propriété Id au public, cela fonctionne bien. Quelqu'un peut-il me dire si je fais quelque chose, ou au moins si c'est même possible?
Vous pouvez utiliser DataContractSerializer
(mais notez que vous ne pouvez pas utiliser d'attributs xml - uniquement des éléments xml):
using System;
using System.Runtime.Serialization;
using System.Xml;
[DataContract]
class MyObject {
public MyObject(Guid id) { this.id = id; }
[DataMember(Name="Id")]
private Guid id;
public Guid Id { get {return id;}}
}
static class Program {
static void Main() {
var ser = new DataContractSerializer(typeof(MyObject));
var obj = new MyObject(Guid.NewGuid());
using(XmlWriter xw = XmlWriter.Create(Console.Out)) {
ser.WriteObject(xw, obj);
}
}
}
Alternativement, vous pouvez implémenter IXmlSerializable
et tout faire vous-même - mais cela fonctionne avec XmlSerializer
, au moins.
Vous pouvez utiliser le System.Runtime.Serialization.NetDataContractSerializer
. Il est plus puissant et corrige quelques problèmes du sérialiseur Xml classique.
Notez qu'il existe différents attributs pour celui-ci.
[DataContract]
public class X
{
[DataMember]
public Guid Id { get; private set; }
}
NetDataContractSerializer serializer = new NetDataContractSerializer();
TextWriter tw = new StreamWriter(_location);
serializer.Serialize(tw, obj);
Modifier:
Mise à jour basée sur le commentaire de Marc: Vous devriez probablement utiliser System.Runtime.Serialization.DataContractSerializer
dans votre cas pour obtenir un XML propre. Le reste du code est le même.
Les champs en lecture seule ne seront pas sérialisés à l'aide de la variable XmlSerializer
; cela est dû à la nature du mot clé readonly
.
De MSDN:
Le mot clé readonly est un modificateur que vous pouvez utiliser sur les champs. Lorsqu'une déclaration de champ inclut un modificateur readonly, les assignations aux champs introduits par la déclaration ne peuvent s'effectuer que dans le cadre de la déclaration ou dans un constructeur de la même classe.
Donc ... vous auriez besoin de définir la valeur des champs dans le constructeur par défaut ...
Ce n'est pas possible avec ce mode de sérialisation particulier (voir les autres commentaires pour des solutions de contournement). Si vous voulez vraiment laisser votre mode de sérialisation tel quel, vous devez contourner les limites de la structure de celui-ci. Voir cet exemple
Esentiellement, cochez la propriété public
, mais émettez une exception si vous y accédez à un moment autre que la désérialisation.