2009-02-26 9 views
10

J'essaie de trouver un moyen de changer le comportement de sérialisation d'une propriété.Redéfinition une propriété avec un attribut

Disons que j'ai une situation comme celle-ci:

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

    // other useful properties ... 
} 

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

    // other useful properties ... 
} 

Maintenant, je veux sérialisation EmployeeRecord. Je ne veux pas que la propriété LastUpdated de la classe Record soit sérialisée. (Je veux que LastUpdated soit sérialisé lorsque je sérialise Record, cependant).

D'abord, j'essayé de cacher la propriété LastUpdated en utilisant le mot-clé nouveau, puis en ajoutant l'attribut XmlIgnore:

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

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

Mais cela ne fonctionne pas. Ensuite, j'ai essayé de faire la base LastUpdated virtuelle il et en remplaçant, en gardant l'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 ... 
} 

Cela ne fonctionne pas non plus. Dans les deux tentatives, LastUpdated a ignoré l'attribut XmlIgnore et s'est contenté de son activité de sérialisation.

Y at-il un moyen de faire ce que je suis en train de faire arriver?

+0

Comment procédez-vous à la sérialisation? Parce que si vous utilisez la sérialisation binaire, l'attribut XmlIgnore ne fera pas beaucoup de bien. –

+0

J'utilise XmlSerializer –

+0

Vous utiliseriez l'attribut NonSerialized pour la sérialisation binaire. – snarf

Répondre

17

D'abord, le [Serializable] attr n'a rien à voir avec le XmlSerializer. C'est un hareng rouge. [Serializable] est significatif pour System.Runtime.Serialization, tandis que XmlSerializer se trouve dans System.Xml.Serialization. Si vous décorez votre classe avec [Serializable] et vos membres avec [XmlIgnore] alors vous êtes probablement confondu avec d'autres lecteurs de votre code.

XmlSerialization dans .NET est très flexible. Selon la façon dont la sérialisation est effectuée, directement par vous ou indirectement, disons par l'exécution des services Web, vous avez différentes façons de contrôler les choses.

Une option consiste à utiliser la propriété propertyName Modèle spécifié pour activer ou désactiver la propriété dans XML Serialization. Supposons que vous ayez ce code:

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

Ensuite, si LastModifiedSpecified est fausse dans une instance, le champ LastModified ne sera pas sérialisé pour cette instance. Dans le constructeur de votre type, vous pouvez définir LastModifiedSpecified comme étant toujours vrai dans le type de base et toujours false dans le type dérivé. Le booléen réel - LastModifiedSpecified - n'est jamais sérialisé car il est marqué XmlIgnore.

Cette petite astuce est documentée here. Votre autre option consiste à utiliser XmlAttributeOverrides, qui est un moyen de fournir dynamiquement l'ensemble des attributs de sérialisation XML (comme XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute, etc.) - en fournissant dynamiquement ces attributs au sérialiseur lors de l'exécution . Le XmlSerializer, au lieu d'inspecter le type lui-même pour ces attributs, va simplement parcourir la liste des attributs de substitution fournis à son constructeur. Ceci est illustré plus en détail par here.

Dans votre cas, vous fournir un XmlIgnoreAttribute comme une dérogation, mais seulement lors de la sérialisation du type dérivé.(ou quoi que ce soit) Cela ne fonctionne que lorsque vous instanciez directement XmlSerializer - il ne fonctionnera pas lorsque la sérialisation est implicitement exécutée par le moteur d'exécution, comme avec les services Web.

À la votre!

+0

Wow, je n'avais jamais entendu parler du motif Specified auparavant. Travaillé comme un charme! –

8

Le mieux que je peux penser ...

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

En fait, il y a quelques modèles qui XmlSerializer respecte; public bool ShouldSerialize*(), et public bool *Specified {get;set;} (notez que vous devriez marquer *Specified avec [XmlIgnore] aussi ...).

Pas très élégant, j'accorde; mais XmlSerializer ne regarde que les membres publics, donc vous ne pouvez même pas les cacher (court de [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]).