2009-12-05 2 views
5

C# - .net 3.5Une méthode qui s'exécute à chaque fois qu'une propriété de classe est accédée (get ou set)?

J'ai une famille de classes qui hérite de la même classe de base. Je souhaite qu'une méthode de la classe de base soit appelée à chaque fois qu'une propriété d'une classe dérivée est accédée (get ou set). Cependant, je ne veux pas écrire de code dans chaque propriété pour appeler la classe de base ... au lieu de cela, j'espère qu'il y a un moyen déclaratif de "couler" cette activité dans la classe de base.

Ajout d'un peu de piquant à l'exigence, j'ai besoin de déterminer le nom de la propriété qui a été accédé, la valeur de la propriété et son type.

J'imagine que la solution serait une combinaison intelligente d'un délégué, de génériques et de réflexion. Je peux envisager de créer un certain type de tableau d'assignations de délégués lors de l'exécution, mais iterer sur le MemberInfo dans le constructeur aurait un impact sur les performances plus que je ne le voudrais. Encore une fois, j'espère qu'il existe un moyen plus «déclaratif» de le faire.

Toutes les idées sont les plus appréciées!

Répondre

2

Je ne crois pas que ce soit possible de le faire de façon déclarative, je ne l'ai jamais vu faire de cette façon. Cependant, vous pouvez implémenter l'interface INotifyPropertyChanged sur votre classe de base et avoir l'implémentation de l'interface dans la classe de base. Quelque chose comme ceci:

public class A : INotifyPropertyChanged 
{ 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    protected virtual void RaiseOnPropertyChanged(object sender, string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      PropertyChanged(sender, new PropertyChangedEventArgs(propertyName); 
    } 

    public A() 
    { 
     this.PropertyChanged += new PropertyChangedEventHandler(A_PropertyChanged); 
    } 

    void A_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     //centralised code here that deals with the changed property 
    } 
} 


public class B : A 
{ 
    public string MyProperty 
    { 
     get { return _myProperty; } 
     set 
     { 
      _myProperty = value; 
      RaiseOnPropertyChanged(this, "MyProperty"); 
     } 
    } 

    public string _myProperty = null; 
} 
+0

Je tiens également à souligner que si INotifyPropertyChanged vous permet de passer un nom de propriété, il ne faut pas qu'un concepteur de fusée pousse le concept un peu plus loin et écrive votre propre version de l'interface qui permet également de passé. Bien que ce que vous proposez, bien que cela puisse sembler intelligent en théorie, va ajouter BEAUCOUP de surcharge à votre application, et vous devrez envisager d'avoir des commutations de compilation conditionnelles dans votre code. – slugster

4

Vous ne pouvez pas le faire automatiquement, mais vous pouvez obtenir environ 95% gratuitement. Ceci est un cas classique pour programmation orientée aspect. Découvrez PostSharp, qui a la classe OnFieldAccessAspect. Voici comment vous pouvez résoudre votre problème:

[Serializable] 
public class FieldLogger : OnFieldAccessAspect { 
    public override void OnGetValue(FieldAccessEventArgs eventArgs) { 
     Console.WriteLine(eventArgs.InstanceTag); 
     Console.WriteLine("got value!"); 
     base.OnGetValue(eventArgs); 
    } 

    public override void OnSetValue(FieldAccessEventArgs eventArgs) { 
     int i = (int?)eventArgs.InstanceTag ?? 0; 
     eventArgs.InstanceTag = i + 1; 
     Console.WriteLine("value set!"); 
     base.OnSetValue(eventArgs); 
    } 

    public override InstanceTagRequest GetInstanceTagRequest() { 
     return new InstanceTagRequest("logger", new Guid("4f8a4963-82bf-4d32-8775-42cc3cd119bd"), false); 
    } 
} 

Maintenant, tout ce qui hérite de FieldLogger va obtenir le même comportement. Presto!

Questions connexes