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.