¿Ya se ha agregado un controlador de eventos?

¿Hay alguna forma de saber si un controlador de eventos se ha agregado a un objeto? Estoy serializando una lista de objetos dentro / fuera del estado de la sesión para que podamos usar el estado de la sesión basada en SQL … Cuando un objeto en la lista tiene una propiedad cambiada necesita ser marcado, que el controlador de eventos se ocupó adecuadamente antes . Sin embargo, ahora, cuando los objetos están deserializados, no obtienen el controlador de eventos.

En un ataque de leve molestia, acabo de agregar el controlador de eventos a la propiedad Obtener que accede al objeto. Se llama ahora, lo que es genial, excepto que se llama como 5 veces, así que creo que el controlador solo se agrega cada vez que se accede al objeto.

Es lo suficientemente seguro como para ignorarlo, pero prefiero que sea mucho más limpio comprobando si el controlador ya se ha agregado, así que solo lo hago una vez.

¿Es eso posible?

EDITAR: No necesariamente tengo control total sobre qué controladores de eventos se agregan, por lo que solo verificar si no es lo suficientemente bueno.

Desde afuera de la clase de definición, como @Telos menciona, solo puedes usar EventHandler en el lado izquierdo de a += o a -= . Por lo tanto, si tiene la capacidad de modificar la clase de definición, puede proporcionar un método para realizar la verificación comprobando si el controlador de eventos es null ; de ser así, no se ha agregado ningún controlador de eventos. Si no es así, entonces puede y puede recorrer los valores en Delegate.GetInvocationList . Si uno es igual al delegado que desea agregar como controlador de eventos, entonces sabrá que está allí.

 public bool IsEventHandlerRegistered(Delegate prospectiveHandler) { if ( this.EventHandler != null ) { foreach ( Delegate existingHandler in this.EventHandler.GetInvocationList() ) { if ( existingHandler == prospectiveHandler ) { return true; } } } return false; } 

Y esto podría modificarse fácilmente para convertirse en “agregar el controlador si no está allí”. Si no tiene acceso a las entrañas de la clase que está exponiendo el evento, puede que necesite explorar -= y += , como lo sugiere @Lou Franco.

Sin embargo, es mejor que reexamine la forma en que está poniendo en servicio y retirando estos objetos, para ver si no puede encontrar una forma de rastrear esta información usted mismo.

Recientemente llegué a una situación similar en la que necesitaba registrar un controlador para un evento solo una vez. Descubrí que puede anular el registro de forma segura primero, y luego registrarse de nuevo, incluso si el controlador no está registrado en absoluto:

 myClass.MyEvent -= MyHandler; myClass.MyEvent += MyHandler; 

Tenga en cuenta que al hacer esto cada vez que registre su controlador, se asegurará de que su controlador esté registrado solo una vez. Me parece una buena práctica 🙂

Si este es el único controlador, puede verificar si el evento es nulo, si no es así, se ha agregado el controlador.

Creo que puede llamar de manera segura – = en el evento con su controlador, incluso si no se agrega (si no, podría atraparlo), para asegurarse de que no está allí antes de agregar.

Este ejemplo muestra cómo usar el método GetInvocationList () para recuperar delegates a todos los controladores que se han agregado. Si está buscando ver si se ha agregado un manejador (función) específico, entonces puede usar una matriz.

 public class MyClass { event Action MyEvent; } ... MyClass myClass = new MyClass(); myClass.MyEvent += SomeFunction; ... Action[] handlers = myClass.MyEvent.GetInvocationList(); //this will be an array of 1 in this example Console.WriteLine(handlers[0].Method.Name);//prints the name of the method 

Puede examinar varias propiedades en la propiedad Método del delegado para ver si se ha agregado una función específica.

Si está buscando ver si solo hay uno adjunto, puede probar null.

Si entiendo tu problema correctamente, es posible que tengas problemas mayores. Usted dijo que otros objetos pueden suscribirse a estos eventos. Cuando el objeto se serializa y se deserializa, los otros objetos (aquellos sobre los que no se tiene control) perderán sus controladores de eventos.

Si no está preocupado por eso, mantener una referencia a su controlador de eventos debería ser lo suficientemente bueno. Si le preocupan los efectos colaterales de que otros objetos pierdan sus manejadores de eventos, entonces puede querer reconsiderar su estrategia de almacenamiento en caché.

Estoy de acuerdo con la respuesta de Alf, pero es poca la modificación, es usar,

  try { control_name.Click -= event_Click; main_browser.Document.Click += Document_Click; } catch(Exception exce) { main_browser.Document.Click += Document_Click; } 
 EventHandler.GetInvocationList().Length > 0