C#: Gestión de Eventos Personalizados

[forTips] .NET

Algo con lo que no tratamos muy a menudo, ya sea por pereza, falta de experiencia o simplemente por que hacemos las cosas de otro modo, son los eventos.

Definición aproximada sobre su uso

Conjunto de métodos o acciones que se ejecutan al darse una cierta condición, la cual ejecutará esos métodos o acciones que se hayan suscrito al evento en cuestión

Son algo tan simple de declarar como esto:

public event EventHandler MyEvent;

Y nos suscribimos a ellos con un código similar a uno de estos:

MyEvent += (o, args) => { /* Do something */ };
MyEvent += delegate(object o, EventArgs args) { /* Do something */ };
MyEvent += MyCustomFunction;

private void MyCustomFunction(object sender, EventArgs eventArgs)
{
    /* Do something */
}

Del mismo modo, es posible desenlazarse del evento, aunque para ello es necesario que el delegado sea una función y no un delegado declarado en línea:

MyEvent -= MyCustomFunction;

Y a partir de aquí, normalmente, ya no se sabe que hacer con ellos del todo, todo el mundo sabe que nos podemos suscribir a un evento por ejemplo, pero no como hacer esta gestión. Y muchas veces no se sabe si es posible suscribirse N veces al mismo evento o solamente una.

Pues bien, primero de todo, es posible suscribirse tantas veces como se quiera a un evento, aunque si se realiza bien la gestión de la suscripción; podemos evitar que todas las suscripciones sean aceptadas o por lo menos tenidas en cuenta a la hora de lanzar el evento.

Gestionemos las suscripciones

En realidad, o por lo menos en mi experiencia, un evento no tiene mucho más misterio; aunque aún nos queda un as en la manga. Podemos definir que hacer con ese delegado que asociamos al evento en el momento de suscribirnos a este como si fuera una propiedad más de una clase.

private EventHandler _myEvent;
public event EventHandler MyEvent
{
    add { _myEvent += value; }
    remove { _myEvent -= value; }
}

Esto quiere decir que podemos evitar que ciertos objetos se asocien a nuestros eventos realizando un control en la clausula add. Y de la misma forma realizar una gestión en la clausula remove. Y así conseguimos un mayor control de nuestro evento y los delegados asociados. Podríamos crear por ejemplo un evento del que nunca nos pudiésemos desenlazar por ejemplo.

Y para finalizar un truquito más, como no ;P

Al realizar la gestión de nuestros delegados en el evento hay un método que considero bastante importante ya que nos da información de todos los métodos y acciones que tenemos asociados GetInvocationList(), el cual podremos usar del siguiente modo.

private EventHandler _myEvent;
public event EventHandler MyEvent
{
    add { _myEvent += value; }
    remove { _myEvent -= value; }
}

public void RaiseMyEvent()
{
   //This code must be raised based on some conditions
   _myEvent.GetInvocationList().ToList().ForEach(a => a.DynamicInvoke());
}

Y como podréis imaginar, podríamos filtrar que queremos ejecutar y que no según nuestros criterios.

Conclusiones

Los eventos no dejan de ser complejos de usar, debido a que no estamos acostumbrados a ellos. Pero con unas pocas ganas e imaginación, se pueden realizar sistemas complejos fáciles de extender a quien facilitemos el acceso a nuestras librerías.