Sostituzione di una proprietà con un attributo

Sto cercando di trovare un modo per modificare il comportamento di serializzazione di una proprietà.

Diciamo che ho una situazione come questa:

[Serializable] public class Record { public DateTime LastUpdated {get; set; } // other useful properties ... } public class EmployeeRecord : Record { public string EmployeeName {get; set; } // other useful properties ... } 

Ora voglio serializzare EmployeeRecord. Non voglio che la proprietà LastUpdated della class Record venga serializzata. (Voglio che LastUpdated sia serializzato quando serializzo Record, però).

Per prima cosa ho provato a hide la proprietà LastUpdated usando la nuova parola chiave e poi aggiungendo l’attributo XmlIgnore:

 public class EmployeeRecord : Record { public string EmployeeName {get; set; } [XmlIgnore] public new DateTime LastUpdated {get; set; } // other useful properties ... } 

Ma quello non ha funzionato. Poi ho provato a rendere virtuale la base LastUpdated e a sovrascriverla, mantenendo l’attributo:

 [Serializable] public class Record { public virtual DateTime LastUpdated {get; set; } // other useful properties ... } public class EmployeeRecord : Record { public string EmployeeName {get; set; } [XmlIgnore] public override DateTime LastUpdated {get; set; } // other useful properties ... } 

Questo non ha funzionato neanche. In entrambi i tentativi, LastUpdated ha ignorato l’attributo XmlIgnore e ha svolto con piacere la propria attività di serializzazione.

C’è un modo per far accadere quello che sto cercando di fare?

Innanzitutto, il [Serializable] attr non ha nulla a che fare con XmlSerializer. Questa è un’aringa rossa. [Serializable] è significativo per System.Runtime.Serialization, mentre XmlSerializer risiede in System.Xml.Serialization. Se stai decorando la tua class con [Serializable] e i tuoi membri con [XmlIgnore], probabilmente stai confondendo te stesso o altri lettori del tuo codice.

XmlSerialization in .NET è molto flessibile. A seconda di come viene eseguita la serializzazione, direttamente da te o indirettamente, ad esempio dal runtime dei servizi Web, hai diversi modi per controllare le cose.

Un’opzione è usare il pattern PropertyName Specified per triggersre o distriggersre la proprietà in Serialization XML. Supponiamo di avere questo codice:

 public class TypeA { public DateTime LastModified; [XmlIgnore] public bool LastModifiedSpecified; } 

Quindi, se LastModifiedSpecified è falso in un’istanza, il campo LastModified non verrà serializzato per quell’istanza. Nel costruttore per il tuo tipo, puoi impostare LastModifiedSpecified per essere sempre vero nel tipo di base e sempre falso nel tipo derivato. Il valore booleano effettivo – LastModifiedSpecified – non viene mai serializzato perché è contrassegnato come XmlIgnore.

Questo piccolo trucco è documentato qui .

L’altra opzione è usare XmlAttributeOverrides, che è un modo di fornire dynamicmente il set di attributi di serializzazione XML (come XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute e così via …) – fornendo in modo dinamico tali attributi al serializzatore in fase di runtime. XmlSerializer, invece di controllare il tipo stesso per quegli attributi, passerà semplicemente attraverso l’elenco degli attributi di sostituzione forniti al suo costruttore.

  var overrides = new XmlAttributeOverrides(); // ....fill the overrides here.... // create a new instance of the serializer specifying overrides var s1 = new XmlSerializer(typeof(Foo), overrides); // serialize as normal, here. 

Questo è illustrato in maggior dettaglio qui .

Nel tuo caso, dovresti fornire un XmlIgnoreAttribute come override, ma solo quando serializzi il tipo derivato. (o qualsiasi altra cosa) Funziona solo quando istanziate direttamente XmlSerializer – non funzionerà quando la serializzazione viene eseguita implicitamente dal runtime, come con i servizi Web.

Saluti!

Il meglio che posso pensare …

 [Serializable] public class Record { public DateTime LastUpdated {get; set; } public virtual bool ShouldSerializeLastUpdated() {return true;} // other useful properties ... } public class EmployeeRecord : Record { public string EmployeeName {get; set; } public override bool ShouldSerializeLastUpdated() {return false;} // other useful properties ... } 

Fondamentalmente, ci sono alcuni modelli che XmlSerializer rispetta; public bool ShouldSerialize*() e public bool *Specified {get;set;} (nota che dovresti contrassegnare *Specified con [XmlIgnore] …).

Non molto elegante, lo concederò; ma XmlSerializer guarda solo membri pubblici, quindi non puoi nemmeno nasconderli (a meno di [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)] ).