2011-06-29 18 views
6

¿Cómo podría refactorizar el método¿Cómo evitar métodos anónimos en la suscripción de eventos "dinámicos"?

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source, 
              string propertyName) 
{ 
    source.PropertyChanged += (o, e) => 
    { 
     if (e.PropertyName == propertyName) 
      MyMagicMethod(); 
    }; 
} 

si deseaba evitar el uso del método anónimo aquí?

+0

El truco aquí no es el método anónimo: es * el cierre * que se usa. La única otra manera que viene a la mente es crear un nuevo objeto que implemente una propiedad/propiedad 'PropertyName' o similar, así como un manejador de eventos' OnPropertyChanged' y el cableado up y ... ick. –

+0

@pst: Gracias por el comentario. Supongo que todavía estoy un poco confuso acerca de los aspectos internos aquí. Leyendo http://csharpindepth.com/Articles/Chapter5/Closures.aspx ahora. =) – Jens

Respuesta

4

Implementar el cierre que está implícita creada por el lambda explícita:

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source, 
              string propertyName) 
{ 
    var listener = new MyPropertyChangedListener(propertyName); 
    source.PropertyChanged += listener.Handle; 
} 

class MyPropertyChangedListener 
{ 
    private readonly string propertyName; 

    public MyPropertyChangedListener(string propertyName) 
    { 
     this.propertyName = propertyName; 
    } 

    public void Handle(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == this.propertyName) 
     { 
      // do something 
     } 
    } 
} 
+0

¡Gracias! Esto es lo que realmente significa mi lambda en el interior? Interesante. =) – Jens

1

Usted puede manejar esto por tener un solo controlador de eventos para todas las instancias que utiliza un diccionario de instancias de que sigue:

private Dictionary<INotifyPropertyChanged, List<string>> sourceMap = 
    new Dictionary<INotifyPropertyChanged, List<string>>(); 

private void ListenToPropertyChangedEvent(INotifyPropertyChanged source, 
              string propertyName) 
{ 
    if (sourceMap.ContainsKey(source)) 
     sourceMap[source].Add(propertyName); 
    else 
    { 
     source.PropertyChanged += source_PropertyChanged; 
     sourceMap[source] = new List<string> { propertyName }; 
    } 
} 

void source_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    var source = sender as INotifyPropertyChanged; 
    var list = sourceMap[source]; 
    if (list.Contains(e.PropertyName)) 
     MyMagicMethod(); 
} 

Esta versión no tiene ningún error de comprobación o eliminación, pero demuestra la técnica. Es particularmente valioso si escuchas varias propiedades de la misma fuente. Esto se debe a que solo agrega un único controlador al evento PropertyChanged por instancia.

+0

Gracias por su respuesta! De hecho, podría escuchar varias propiedades de la misma fuente. Puede haber un poco más de contabilidad involucrado con este enfoque, ya que no quiero evitar que las fuentes sean recolectadas como basura al hacer referencia en el diccionario, pero eso puede ser administrado. – Jens

0

No estoy seguro exactamente lo que usted está tratando de lograr o por qué usted no desea utilizar los métodos anónimos, pero se puede hacer algo más genérico:

private PropertyChangedEventHandler GetHandler 
     (Func<PropertyChangedEventArgs, bool> test, Action toInvoke) 
    { 
     return new PropertyChangedEventHandler(
      (o, e) => 
      { 
       if (test(e)) 
       toInvoke(); 
      }); 
    } 

A continuación, puede usarlo de esta manera:

source.PropertyChanged += GetHandler     
      (
       p => p.PropertyName == propertyName, MyMagicMethod 
      ); 

De esta forma, su prueba if y el grupo de métodos de destino se pueden intercambiar fácilmente. Su controlador de eventos también está fuertemente tipado en lugar de anónimo.

+0

Mis compañeros de trabajo no se sienten cómodos con métodos anónimos, así que trato de evitarlos siempre que sea posible. – Jens

+0

Técnicamente, un PropertyChangedEventHandler es un delegado específicamente destinado a escuchar eventos que propagan PropertyChangedEventArgs, por lo que cada vez que utilice un EventHandler fuertemente tipado, como que está evitando el uso de un método anónimo, siempre que pase un grupo de métodos, que es una función (menos paréntesis, bc no la está invocando inmediatamente) a la que desea llamar cuando se activa el evento. No diría que es necesario crear una clase completamente nueva que encapsule la escucha de eventos, eso es lo que hace un EventHandler. –

Cuestiones relacionadas