2011-05-21 17 views
7

Estoy en el proceso de crear un marco en el cual proporciono la clase base y los implementadores del marco heredarán de la clase base y proporcionarán propiedades y métodos adicionales. En la clase base, me gustaría tener una forma de observar cuando se cambia el valor de una propiedad. La propiedad puede ser de la clase base o en cualquiera de las subclases. Sé que a través de la reflexión, puedo determinar la lista de propiedades de cualquier instancia, pero ¿hay alguna manera de rastrear el valor cambiante de la propiedad?C# - Intercepción de cambios de propiedad en las subclases

Aquí es un ejemplo muy simplista de lo que estoy diciendo:

public class BaseClass 
{ 
    public string BaseClassProperty { get; set; } 

    public void DoSomethingWhenEitherPropertyGetsChanged() 
    { 

    } 
} 

public class SubClass : BaseClass 
{ 
    public string SubClassProperty { get; set; } 
} 

¿Qué puedo hacer para tener DoSomethingWhenEitherPropertyGetsChanged se ejecutan cuando alguna de las propiedades tiene su valor cambiado.

+0

incluso en la clase base, se le va a tener que llamar 'DoSomethingWhenEitherPropertyGetsChanged()' en su colocador propiedad para que pueda hacer lo mismo en los emisores de llamada de propiedades de la subclase. –

+0

Para cualquiera que esté interesado en implementar un interceptor, eche un vistazo a [TinyInterceptor] (https://github.com/Jalalx/TinyInterceptor) – Jalal

Respuesta

4

Puede usar notifypropertyweaver para este fin. Hace exactamente lo que quieres. Aquí hay un enlace:

Desde la página principal de código abierto:

Usos IL tejer (a través de http://www.mono-project.com/Cecil) para inyectar código en INotifyPropertyChanged propiedades.

  • ningún atributo necesario
  • No hay referencias requieren
  • Ninguna clase base requerida
  • Soporta .NET 3.5, .NET 4, Silverlight 3, 4 Silverlight, Silverlight 5 y Windows Phone 7
  • Apoyos perfil de cliente modo
+0

¡Gracias! Después de una prueba rápida, ¡esto parece ser justo lo que necesitaba! –

+0

Me alegro de poder ayudar. Es un proyecto realmente genial. –

+0

no encontrado ahora :( – kaspartus

3

Probablemente usaría Postsharp y crearía un atributo heredado que inyectara código de interceptación en todas las propiedades públicas. Marcar el atributo como heredado también debe adjuntarlo a todas las subclases automáticamente.

+0

¿Está diciendo que se debe crear un atributo en la 'BaseClass' que interceptará al colocador? método en todas las propiedades de la clase base, así como las clases heredadas? –

+0

Postsharp define algunos atributos que básicamente te permiten inyectar código en todo tipo de métodos. – ChrisWue

0

Su mejor opción sería la que CrisWue recomendó y usar postesharp u otro postprocesador para inyectar el comportamiento en sus propiedades. Aparte de eso, creo que necesitaría llamar DoSomethingWhenEitherPropertyGetsChanged() manualmente dentro de sus propiedades.

Si está creando una biblioteca que es consumida por personas que no sean usted o su organización, un post-procesador puede no ser el camino correcto ya que agrega la herramienta de terceros como otro requisito para su proceso de compilación.

1

Escribí mi propia idea de sus requisitos, pero no estoy seguro si se adapta a sus necesidades. INotifyProperty cambiado es algo en lo que también podrías mirar, pero realmente no me gusta porque es como conectar espeleos. Sin embargo, tal vez esto te dará algunas ideas creativas.

Lo que hace esto, le permite usar ObservableObject como para todos sus tipos de propiedades. Al hacer esto, cada propiedad tendrá un evento ObjectChanged al que puede conectarse. Las estafas son que debe inicializar todas sus propiedades en el constructor para evitar una excepción NullReferenceException en algún lugar de su código.

Este ejemplo utiliza tres clases.

  • ObservableObject.cs
  • Employee.cs
  • Program.cs

ObservableObject.cs

//----------------------------------------------------------------------------- 
    // <copyright file="ObservableObject.cs" company="DCOM Productions"> 
    //  Copyright (c) DCOM Productions. All rights reserved. 
    // </copyright> 
    //----------------------------------------------------------------------------- 

    namespace PropertyChangedEventExample { 
     using System; 

     public class ObservableObject : Object { 
      /// <summary> 
      /// Expose the default constructor 
      /// </summary> 
      public ObservableObject() { 
       // No default implementation 
      } 

      private object m_Object = null; 
      /// <summary> 
      /// Base object 
      /// </summary> 
      public object Object { 
       get { 
        return m_Object; 
       } 
       set { 
        if (m_Object != value) { 
         m_Object = value; 
         OnObjectChanged(this, EventArgs.Empty); 
        } 
       } 
      } 

      /// <summary> 
      /// Triggered when the value of this object has changed. 
      /// </summary> 
      public event System.EventHandler<EventArgs> ObjectChanged; 
      /// <summary> 
      /// EventHandler wire-up 
      /// </summary> 
      protected virtual void OnObjectChanged(object sender, System.EventArgs e) { 
       if (ObjectChanged != null) { 
        ObjectChanged(sender, e); 
       } 
      } 

      /// <summary> 
      /// Gets the value 
      /// </summary> 
      public object Get() { 
       return this.Object; 
      } 

      /// <summary> 
      /// Sets the value 
      /// </summary> 
      public void Set(object value) { 
       this.Object = value; 
      } 
     } 
    } 

Employee.cs

//----------------------------------------------------------------------------- 
    // <copyright file="Employee.cs" company="DCOM Productions"> 
    //  Copyright (c) DCOM Productions. All rights reserved. 
    // </copyright> 
    //----------------------------------------------------------------------------- 

    namespace PropertyChangedEventExample { 
     using System; 

     public class Employee { 
      /// <summary> 
      /// Expose default constructor 
      /// </summary> 
      public Employee() { 
       Name = new ObservableObject(); 
      } 

      /// <summary> 
      /// Gets or sets the name 
      /// </summary> 
      public ObservableObject Name { 
       get; 
       set; 
      } 
     } 
    } 

Program.cs

//----------------------------------------------------------------------------- 
    // <copyright file="Program.cs" company="DCOM Productions"> 
    //  Copyright (c) DCOM Productions. All rights reserved. 
    // </copyright> 
    //----------------------------------------------------------------------------- 

    namespace PropertyChangedEventExample { 
     using System; 

     class Program { 
      static void Main(string[] args) { 
       Employee employee = new Employee(); 
       employee.Name.Set("David"); 
       employee.Name.ObjectChanged += new EventHandler<EventArgs>(Name_ObjectChanged); 
       employee.Name.Set("Dave"); 
       Console.ReadKey(true); 
      } 

      static void Name_ObjectChanged(object sender, EventArgs e) { 
       ObservableObject employee = sender as ObservableObject; 
       Console.WriteLine("Name changed to {0}", employee.Get()); 
      } 
     } 
    }