2009-12-05 14 views
5

C# - .NET 3.5Un método que se ejecuta cada vez que se accede a una propiedad de clase (get o set)?

que tienen una familia de clases que heredan de la misma clase base. Quiero que se invoque un método en la clase base cada vez que se accede a una propiedad en una clase derivada (get o set). Sin embargo, no quiero escribir código en cada propiedad para llamar a la clase base ... en su lugar, espero que haya una forma declarativa de "hundir" esta actividad en la clase base.

Agregando un poco de picante al requisito, necesito determinar el nombre de la propiedad a la que se accedió, el valor de la propiedad y su tipo.

Imagino que la solución sería una inteligente combinación de delegado, genéricos y reflexión. Puedo imaginar la creación de algún tipo de matriz de asignaciones de delegados en tiempo de ejecución, pero iterar sobre el MemberInfo en el constructor tendría un impacto en el rendimiento más de lo que me gustaría. Nuevamente, espero que haya una forma más directa y "declarativa" de hacer esto.

¡Todas las ideas son muy apreciadas!

Respuesta

2

No creo que esto sea posible de manera declarativa, nunca lo he visto hecho de esa manera. Sin embargo, lo que puede hacer es implementar la interfaz INotifyPropertyChanged en su clase base y tener la implementación de la interfaz en la clase base. Algo como esto:

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

Debo señalar también que aunque INotifyPropertyChanged le permite pasar un nombre de propiedad, no hace falta ser un científico espacial para llevar el concepto un paso más allá y escribir su propia versión de la interfaz que también permita que el valor de la propiedad, etc. pasado. Aunque lo que está proponiendo, si bien puede sonar ingenioso en teoría, va a agregar MUCHA sobrecarga a su aplicación, y tendrá que considerar tener interruptores de compilación condicionales en su código. – slugster

4

No puede hacerlo automáticamente, pero puede obtener casi el 95% de forma gratuita. Este es un caso clásico para programación orientada a aspectos. Consulte PostSharp, que tiene la clase OnFieldAccessAspect. He aquí cómo usted puede resolver su 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); 
    } 
} 

Ahora, todo lo que se hereda de FieldLogger va a tener el mismo comportamiento. ¡Presto!

Cuestiones relacionadas