Domanda

Sto cercando di serializzare un oggetto su XML che ha un numero di proprietà, alcune delle quali sono di sola lettura.

public Guid Id { get; private set; }

Ho contrassegnato la classe [Serializable] e ho implementato l'interfaccia ISerializable.

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

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 è stata gestita:   Impossibile generare una classe temporanea (risultato = 1).   errore CS0200: impossibile assegnare la proprietà o l'indicizzatore "MyObject.Id" - è di sola lettura

Se imposto la proprietà Id su public funziona bene. Qualcuno può dirmi se sto facendo qualcosa, o almeno se è anche possibile?

È stato utile?

Soluzione

Puoi usare DataContractSerializer (ma nota che non puoi usare gli attributi xml - solo 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 almeno con XmlSerializer .

Altri suggerimenti

È possibile utilizzare il 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);

Modifica

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

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

Da MSDN:

  

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

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

Non è possibile 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

In sostanza, contrassegnare la proprietà public , ma generare un'eccezione se si accede in qualsiasi momento diverso dalla deserializzazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top