2009-02-26 5 views
10

Ich versuche, eine Möglichkeit zu finden, das Serialisierungsverhalten einer Eigenschaft zu ändern.Überschreiben einer Eigenschaft mit einem Attribut

Können sagen, ich habe eine Situation wie folgt aus:

[Serializable] 
public class Record 
{ 
    public DateTime LastUpdated {get; set; } 

    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    // other useful properties ... 
} 

Jetzt möchte ich EmployeeRecord serialisiert. Ich möchte nicht, dass die LastUpdated-Eigenschaft aus der Record-Klasse serialisiert wird. (Ich möchte LastUpdated serialisiert werden, wenn ich jedoch Record serialisieren).

Zuerst habe ich versucht, die Eigenschaft Lastupdated versteckt durch die neue Schlüsselwort und dann das XmlIgnore Attribut:

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    [XmlIgnore] 
    public new DateTime LastUpdated {get; set; } 
    // other useful properties ... 
} 

Aber das hat nicht funktioniert. Dann habe ich versucht, so dass die Basislastupdated virtuellen und überschreibt sie, halten das Attribut:

[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 ... 
} 

Dies hat nicht funktioniert entweder. In beiden Versuchen ignorierte die LastUpdated das XmlIgnore-Attribut und ging glücklich über ihre Serialisierung.

Gibt es eine Möglichkeit zu machen, was ich versuche zu tun?

+0

Wie serialisieren Sie es? Wenn Sie die binäre Serialisierung verwenden, wird das XmlIgnore-Attribut nicht viel nutzen. –

+0

Ich verwende XmlSerializer –

+0

Sie würden das NonSerialized-Attribut für die binäre Serialisierung verwenden. – snarf

Antwort

17

Erstens, das [Serializable] Attr hat nichts mit dem XmlSerializer zu tun. Das ist ein Ablenkungsmanöver. [Serializable] ist für System.Runtime.Serialization von Bedeutung, während der XmlSerializer in System.Xml.Serialization lebt. Wenn Sie Ihre Klasse mit [Serializable] und Ihren Mitgliedern mit [XmlIgnore] dekorieren, verwirren Sie sich selbst oder andere Leser Ihres Codes wahrscheinlich.

XmlSerialization in .NET ist sehr flexibel. Abhängig davon, wie die Serialisierung ausgeführt wird, direkt von Ihnen oder indirekt, sagen wir mal von der Web-Service-Laufzeit - Sie haben verschiedene Möglichkeiten, Dinge zu steuern.

Eine Option besteht darin, das Attribut propertyName Angegebenes Muster zu verwenden, um die Eigenschaft in der XML-Serialisierung ein- oder auszuschalten. Angenommen, Sie haben diesen Code:

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

Wenn dann LastModifiedSpecified in einem Fall falsch ist, das LastModified Feld wird nicht für diese Instanz serialisiert werden. Im Konstruktor für Ihren Typ können Sie LastModifiedSpecified so einstellen, dass im Basistyp immer true und im abgeleiteten Typ immer false angegeben ist. Der eigentliche boolean - LastModifiedSpecified - wird niemals serialisiert, da er als XmlIgnore gekennzeichnet ist. Dieser kleine Trick ist dokumentiert here.

Die andere Option ist XmlAttributeOverrides zu verwenden, das ist eine Möglichkeit, dynamisch den Satz von XML-Serialisierung Attribute bereitstellt (wie XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute, und so weiter ...) - dynamisch diese Attribute an den Serializer zur Laufzeit bereitstellt . Anstatt den Typ selbst nach diesen Attributen zu durchsuchen, durchläuft der XmlSerializer nur die Liste der Überschreibungsattribute, die für seinen Konstruktor bereitgestellt werden.

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. 

Dies ist detaillierter here dargestellt.

In Ihrem Fall würden Sie ein XmlIgnoreAttribute als Überschreibung bereitstellen, jedoch nur, wenn Sie den abgeleiteten Typ serialisieren.(oder was auch immer) Dies funktioniert nur, wenn Sie den XmlSerializer direkt instanziieren - er funktioniert nicht, wenn die Serialisierung implizit von der Laufzeit ausgeführt wird, wie bei Web-Services.

Prost!

+0

Wow, ich hatte noch nie zuvor von dem Spezifizierten Muster gehört. Lief wie am Schnürchen! –

8

Das Beste, was ich denken kann ...

[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 ... 
} 

Grundsätzlich gibt es einige Muster, die XmlSerializer Hinsicht; public bool ShouldSerialize*() und public bool *Specified {get;set;} (beachten Sie, dass Sie auch *Specified mit [XmlIgnore] markieren sollten ...).

Nicht sehr elegant, ich werde gewähren; aber XmlSerializer sieht nur öffentliche Mitglieder, so dass Sie sie nicht einmal verstecken können (kurz [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]).

Verwandte Themen