Serializzare i dati dei membri privati

Sto provando a serializzare un object in XML che ha un numero di proprietà, alcune delle quali sono di sola lettura.

public Guid Id { get; private set; } 

Ho segnato la class [Serializable] e ho implementato l’interfaccia ISerializable.

Di seguito è riportato il codice che sto usando per serializzare il mio object.

 public void SaveMyObject(MyObject obj) { XmlSerializer serializer = new XmlSerializer(typeof(MyObject)); TextWriter tw = new StreamWriter(_location); serializer.Serialize(tw, obj); tw.Close(); } 

Sfortunatamente cade sulla prima riga con questo messaggio.

InvalidOperationException non gestito: imansible generare una class temporanea (risultato = 1). errore CS0200: Imansible assegnare la proprietà o l’indicizzatore “MyObject.Id” – è di sola lettura

Se imposto la proprietà Id al pubblico, funziona bene. Qualcuno può dirmi se sto facendo qualcosa, o almeno se è ansible?

È ansible utilizzare DataContractSerializer (ma si noti che non è ansible utilizzare gli attributi xml – solo gli elementi 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); } } } 

In alternativa, puoi implementare IXmlSerializable e fare tutto da solo, ma questo funziona con XmlSerializer , almeno.

È ansible utilizzare System.Runtime.Serialization.NetDataContractSerializer . È più potente e risolve alcuni problemi del classico serializzatore Xml.

Nota che ci sono diversi attributi per questo.

 [DataContract] public class X { [DataMember] public Guid Id { get; private set; } } NetDataContractSerializer serializer = new NetDataContractSerializer(); TextWriter tw = new StreamWriter(_location); serializer.Serialize(tw, obj); 

Modificare:

Aggiornamento basato sul commento di Marc: Probabilmente dovresti usare System.Runtime.Serialization.DataContractSerializer per il tuo caso per ottenere un XML pulito. Il resto del codice è lo stesso.

I campi di sola lettura non verranno serializzati utilizzando XmlSerializer , ciò è dovuto alla natura della parola chiave readonly

Da MSDN:

La parola chiave readonly è un modificatore che puoi utilizzare sui campi. Quando una dichiarazione di campo include un modificatore di sola lettura, le assegnazioni ai campi introdotti dalla dichiarazione possono avvenire solo come parte della dichiarazione o in un costruttore della stessa class.

Quindi … avresti praticamente bisogno di impostare il valore dei campi nel costruttore predefinito …

Non è ansible con quella particolare modalità di serializzazione (vedere gli altri commenti per soluzioni alternative). Se vuoi davvero lasciare la tua modalità di serializzazione così com’è, devi aggirare i limiti del framework su questo. Vedi questo esempio

Esenzialmente, contrassegnare la proprietà public , ma generare un’eccezione se è accessibile in qualsiasi momento diversa dalla deserializzazione.