Inicio > programacion > Notificar cambios de forma sistematica

Notificar cambios de forma sistematica

En los últimos días me surgió la necesidad de notificar a la vista cada vez que ocurrian cambios en el modelo. La solución rápida, aburrida y repetitiva es la de ir a la clase base del modelo y publicar los eventos. Luego ir a cada clase del modelo y en todos los setters agregar el codigo para notificar el cambio.

Haciendo uso de Reflection, delegates anonimos y generics; implementé otra solución que si bien no es super novedosa, me pareció que vale la pena compartir con ustedes.

La clase base del modelo queda asi:

 6 public class BaseModel
 7 {
 8   protected bool setProperty<T>(object sender, T oldValue, T newValue, setDelegate<T> set)
 9   {
10     if ( oldValue.Equals( newValue ) ) return false;
11
12     string propertyName = String.Empty;
13     StackFrame[] stackFrames = new StackTrace().GetFrames();
14     if (stackFrames != null && stackFrames.Length >= 2)
15     {
16       propertyName = stackFrames[1].GetMethod().Name;
17       propertyName = propertyName.Substring(4, propertyName.Length - 4);
18     }
19
20     bool cancel = false;
21     if ( PropertyChanging != null )
22     {
23       var args = new PropertyChangingEventArgs(oldValue, newValue, propertyName, sender);
24       PropertyChanging( this, args );
25       cancel = args.Cancel;
26     }
27
28     if ( cancel ) return false;
29
30     set(newValue);
31
32     if (PropertyChanged != null)
33     {
34       var args = new PropertyChangedEventArgs(oldValue, newValue, propertyName, sender);
35       PropertyChanged(this, args);
36     }
37     return true;
38   }
39
40   protected delegate void setDelegate<T>(T value);
41
42   public event EventHandler<PropertyChangingEventArgs> PropertyChanging;
43   public event EventHandler<PropertyChangedEventArgs>  PropertyChanged;
44 }

y las clases derivadas quedan así:

 1 /// <summary>
 2 /// Child test model
 3 /// </summary>
 4 public class ChildModel : BaseModel
 5 {
 6   private int age;
 7
 8   /// <summary>
 9   /// Gets or sets the age.
10   /// </summary>
11   /// <value>The age.</value>
12   public int Age
13   {
14     get { return age; }
15     set
16     {
17       setProperty( this, age, value, delegate(int val) { age = val; } );
18     }
19   }
20 }

Como ven, igualmente es necesario modificar las clases derivadas para que los set llamen al metodo heredado. Lo bueno es que toda la lógica de notificación queda en la clase base y cualquier cambio en la misma ya no hay que distribuirla entre las derivadas.

Categorías:programacion Etiquetas:,
  1. Septiembre 7, 2009 a las 1:22 am | #1

    Está bueno …. no se puede arreglar el formato para que se lea todo el ancho del código?

    Se me ocurre que se podría delegar (opcionalmente) esto

    if ( oldValue.Equals( newValue ) ) return false;

    para que la clase derivada decida si es necesaria la notificación (en caso que le interese).

    • Septiembre 8, 2009 a las 12:17 am | #2

      Creo que logre arreglarlo… maldito CSS :) Igual no quedo perfecto pero ya es culpa del template.
      Veo que igual entendiste el codigo ya que tu sugerencia es buena!
      Abrazo!

  1. Aún no hay trackbacks