2010-03-15 15 views
0

Je suis en train d'utiliser XmlSerializer de C# pour sauver une classe qui a certaines valeurs qui sont lues par des propriétés (le code étant juste une simple extraction de la valeur sur le terrain), mais mis par les fonctions setter (puisqu'il y a un délégué appelé si la valeur change).En utilisant XmlSerializer .NET avec des propriétés get et fonctions setter

Ce que je fais actuellement est ce genre de chose. L'utilisation prévue est d'utiliser la propriété InT pour lire la valeur et utiliser SetInT pour le définir. Le réglage a des effets secondaires, donc une méthode est plus appropriée qu'une propriété ici. XmlSerializationOnly_InT existe uniquement pour le bénéfice du XmlSerializer (d'où le nom), et ne doit pas être utilisé par le code normal.

class X 
{ 
    public double InT 
    { 
     get { return _inT; } 
    } 

    public void SetInT(double newInT) 
    { 
     if (newInT != _inT) 
     { 
      _inT = newInT; 
      Changed();//includes delegate call; potentially expensive 
     } 
    } 

    private double _inT; 

    // not called by normal code, as the property set is not just a simple 
    // field set or two. 
    [XmlElement(ElementName = "InT")] 
    public double XmlSerializationOnly_InT 
    { 
     get { return InT; } 
     set { SetInT(value); } 
    } 
} 

Cela fonctionne, il est assez facile à faire, et le fichier XML ressemble que vous attendez. C'est du travail manuel cependant, et un peu moche, donc je suis seulement un peu satisfait. Ce que j'aimerais vraiment, c'est pouvoir dire à la sérialisation XML de lire la valeur en utilisant la propriété, et la définir en utilisant la fonction setter. Ensuite, je n'aurais pas besoin de XmlSerializationOnly_InT du tout. Je semble suivre la pratique habituelle en distinguant les ensembles de propriétés et les fonctions de réglage de cette manière, donc je suis sûr que je ne suis pas la seule personne à avoir rencontré cela (bien que google suggère que je pourrais être). Qu'ont fait les autres dans cette situation? Yat-il un moyen facile de persuader le XmlSerializer de gérer ce genre de chose mieux? Sinon, y a-t-il peut-être un autre moyen facile de le faire?

+4

Quelle est la raison d'utiliser une méthode setter plutôt qu'un poseur de propriété? Cela fonctionnerait tout de même, serait plus facile à utiliser, et la sérialisation XML fonctionnerait très bien ... –

+0

Question mise à jour avec une petite note à ce sujet. Voir, par exemple, http://msdn.microsoft.com/en-us/library/ms229054.aspx. –

Répondre

1

EDIT:
Je voudrais vraiment juste faire la part de la fonction setter de la propriété. Si vous le souhaitez, le setter peut déclencher un event et appeler la fonction dans l'événement.

// A delegate type for hooking up change notifications. 
public delegate void ChangedEventHandler(object sender, EventArgs e); 

class X 
{ 
    private double _inT; 

    // An event that clients can use to be notified whenever the 
    // elements of the list change. 
    public event ChangedEventHandler InTChanged; 
    // Invoke the Changed event; called whenever list changes 

    protected virtual void OnChanged(EventArgs e) 
    { 
     if (InTChanged != null) 
      InTChanged(this, e); 
    } 
    public double InT 
    { 
     get { return InT; } 
     set 
     { 
      _inT = newInT; 

      //Invoke InTChanged event here 
      OnChanged(EventArgs.Empty); 
     } 
    } 
} 

Sinon, vous pourriez juste vos propres fonctions de sérialisation et la désérialisation:

class X 
{ 
    public void SetInT(double newInT) 
    { 
     if (newInT != _inT) 
     { 
      _inT = newInT; 
      Changed();//includes delegate call; potentially expensive 
     } 
    } 

    private double _inT; 

    public double InT 
    { 
     get { return InT; } 
    } 
    public XElement SerializeX() 
    { 
     XElement serializedItems = new XElement("X", 
      new XElement("InT", this._inT), 
      new XElement("OtherProperty1", this.OtherProperty1), 
      new XElement("OtherProperty2", this.OtherProperty2)); 
     return serializedItems; 
    } 
    public void DeserializeX(XElement itemXML) 
    { 
     this._inT = Double.Parse(itemXML.Element("InT").Value, 
      CultureInfo.InvariantCulture); 
     this.OtherProperty1 = Double.Parse(
      itemXML.Element("OtherProperty1").Value, 
      CultureInfo.InvariantCulture); 
     this.OtherProperty2 = Double.Parse(
      itemXML.Element("OtherProperty2").Value, 
      CultureInfo.InvariantCulture); 
    } 
} 
+0

Cela ne change-t-il pas le comportement du code? Vous pourriez accidentellement 'x.InT = someDouble' ailleurs et perdre l'appel à Changed(). –

+0

Oui, le nom est juste pour empêcher les gens de l'utiliser! Je ne veux pas du tout la propriété XmlSerializationOnly_InT. Il est seulement là pour donner au sérialiseur quelque chose avec lequel il peut travailler. Idéalement, il y a juste la propriété en lecture seule InT, et la méthode setter SetInT. –

+0

@ brone-Pourriez-vous avoir le setter déclencher un événement et avoir un gestionnaire d'événements qui réside ailleurs qui appelle votre fonction Changed()? Beaucoup de propriétés sont faites de cette façon, et il ne semble pas que cela irait à l'encontre de l'une des pratiques de conception que vous avez posté ci-dessus. –