2009-12-05 13 views
5

C# - .net 3.5Un metodo che viene eseguito ogni volta che si accede a una proprietà di classe (ottieni o imposta)?

Ho una famiglia di classi che ereditano dalla stessa classe base. Voglio che un metodo nella classe base sia invocato ogni volta che si accede a una proprietà in una classe derrived (get o set). Tuttavia, non voglio scrivere codice in ogni proprietà per chiamare la classe base ... invece, spero che ci sia un modo dichiarativo per "affondare" questa attività nella classe base.

Aggiungendo un po 'di pepe al requisito, ho bisogno di determinare il nome della proprietà a cui si è avuto accesso, il valore della proprietà e il suo tipo.

Immagino che la soluzione sia una combinazione intelligente di delegato, generici e riflessioni. Posso immaginare di creare un certo tipo di array di assegnazioni di delegati in fase di esecuzione, ma l'iterazione su MemberInfo nel costruttore influirà sulle prestazioni più di quanto mi piacerebbe. Di nuovo, spero che esista un modo più "dichiarativo" diretto per farlo.

Tutte le idee sono più apprezzate!

risposta

2

Non credo che sia possibile farlo in modo dichiarativo, non l'ho mai visto fare in quel modo. Quello che puoi fare è implementare l'interfaccia INotifyPropertyChanged sulla tua classe base e avere l'implementazione dell'interfaccia nella classe base. Qualcosa del genere:

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

Vorrei anche sottolineare che mentre INotifyPropertyChanged ti permette di passare un nome di proprietà, non ci vuole uno scienziato missilistico per portare il concetto un ulteriore passo avanti e scrivere la tua versione dell'interfaccia che permetta anche il valore della proprietà ecc. passato. Anche se quello che stai proponendo, sebbene possa sembrare intelligente in teoria, aggiungerà un sacco di spese generali alla tua applicazione, e dovrai considerare di avere degli switch di compilazione condizionali nel tuo codice. – slugster

4

Non è possibile farlo automaticamente, ma è possibile ottenere quasi il 95% gratuitamente. Questo è un caso classico per la programmazione orientata agli aspetti . Controlla PostSharp, che ha la classe OnFieldAccessAspect. Ecco come potresti risolvere il tuo problema:

[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); 
    } 
} 

Ora, tutto ciò che eredita da FieldLogger avrà lo stesso comportamento. Presto!

Problemi correlati