Perché le proprietà senza un setter non sono serializzate


101

Ho una classe serializzabile e una delle proprietà nella mia classe genera un Guidnel getter. La proprietà non implementa alcun setter e viene ignorata durante la serializzazione. Perché è così e devo sempre implementare un setter per serializzare la mia proprietà.

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

Ho provato a implementare un setter vuoto e è stato serializzato correttamente.

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

Aggiornamento :

Puoi indicare come devo definire proprietà i cui valori non cambiano mai o quelli per cui il valore è generato internamente?


1
Il secondo esempio serializza correttamente ... Ma cosa succede quando provi a deserializzarlo?
LightStriker

Prova YAXLib [+ , + ]
Sina Iravanian

3
Cordiali saluti, il serializzatore XML ignora [Serializable].
John Saunders

@ JohnSaunders non ne ero a conoscenza.
Konstantin Dinev

Risposte:


60

È una limitazione del XmlSerializerfatto che non serializza le proprietà di sola lettura, ciò che hai fatto nel tuo secondo esempio è essenzialmente l'hack per farlo serializzare, tuttavia, è inutile se hai bisogno di deserializzare in seguito.

In alternativa puoi passare all'utilizzo di DataContractSerializer , è più flessibile.


8
DataContractSerializer richiede anche setter. Questa è una limitazione perché anche se possiamo usarlo per un solo tipo di operazione, diciamo deserializzazione, ma le dichiarazioni devono essere per entrambi altrimenti, il processo di serializzazione non saprà cosa fare con un valore quando sta cercando di serializzare un XML in oggetti.
ryadavilli

7
@ryadavilli tutto ciò che [DataMember]è contrassegnato come viene serializzato utilizzando DataContractSerializer(sola lettura o meno).
James

1
@ James ho scritto quanto sopra perché ho ricevuto alcuni errori in fase di compilazione quando ho provato lo stesso. Ora, quando sono tornato al mio codice e rimosso il setter, sembra che si compili bene. Questo è molto strano e probabilmente compito per casa per me cercare di più su questo.
ryadavilli

3
Ahhh finalmente ho trovato la fonte della mia confusione. Un setter di proprietà non è richiesto per la serializzazione. Tuttavia, se una proprietà non dispone di un setter, l'XML non verrà deserializzato in un oggetto. Lì, i compiti sono finiti.
ryadavilli

1
@ryadavilli sì esattamente, è solo una limitazione XmlSerializerdell'implementazione, si basa sul metodo del setter pubblico. DataContractSerializerè un po 'più intelligente in questo senso (probabilmente usando il riflesso per impostare il campo dietro le quinte).
James

10

Vedere " Introduzione alla serializzazione XML " nella documentazione di MSDN. Tra le altre cose, dice:

Elementi che possono essere serializzati

Gli elementi seguenti possono essere serializzati utilizzando la 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.

Inoltre, vedere " Perché la classe XML-Serializable richiede un costruttore senza parametri "


Inoltre, IXmlSerializable

Oltre ai tipi di cui sopra che possono essere serializzati dal Serializzatore XML, qualsiasi tipo che implementa l'interfaccia IXmlSerializable può essere serializzato e deserializzato. In particolare, ciò significa che i tipi XElement e XDocument possono essere serializzati.

Vedere " Interfaccia IXmlSerializable ".


6

Limitazione di XMLSerializer- Le proprietà senza setter non possono essere serializzate.

Ma puoi usare DataContractSerializerper serializzare private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}

La proprietà dovrebbe essere serializzata come un attributo xml (vedi post originale). Il tuo codice (attributo DataMember) produce un elemento xml. Per quanto ne so, non esiste un modo (pulito) per dire al DataContractSerializer di trasformare una proprietà in un attributo e non in un elemento. DataContractSerializer è carino ma devi sempre tenere a mente questa limitazione.
sth_Weird

2

se vuoi avere setter privati ​​e avere l'oggetto serializzabile / deserializzabile, impliment ISerializable e crea un costruttore come MyObject (SerializationInfo info, StreamingContext context). Un esempio si trova qui .


0

Gli attributi di serializzazione vengono utilizzati per serializzare e deserializzare gli oggetti. XmlSerializer presupporrà che non sia necessario serializzare alcuna proprietà che non dispone di un setter. Il setter verrà utilizzato durante la deserializzazione di una stringa in un oggetto, poiché è necessario creare un'istanza dell'oggetto e quindi il setter verrà utilizzato per popolare il valore della proprietà.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.