English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Evento de C# (Event)

C# orientado a objetos (OOP)

Los eventos son notificaciones enviadas por un objeto para representar la ocurrencia de una operación. Los eventos en .NET siguen el patrón de diseño observador. La clase que desencadena eventos se llama

Publisher (publicador), la clase que recibe las notificaciones se llama Subscriber (suscriptor). Un evento puede tener varios suscriptores. Por lo general, el publicador desencadena un evento cuando ocurre alguna operación. Los suscriptores desean recibir notificaciones cuando ocurre una operación, deben registrarse en el evento y manejarlo.

En C#, los eventos son delegados encapsulados. Dependen del delegado. El delegado define la firma del método del gestor de eventos de la clase suscriptora.

El siguiente gráfico ilustra los eventos en C#.

publicador de eventos y suscriptores

uso de delegados a través de eventos publicador(publisher) clase. Otras clases que aceptan este evento se denominan clase suscriptora (subscriber). Los eventos se declaran y generan en la clase y se asocian a los gestores de eventos mediante delegados de la misma clase u otras clases. La clase que contiene eventos se utiliza para publicar eventos. Esto se conoce como publicación-suscripción(publisher-subscriber) modelo.

publicador(publisher)- Es un objeto que contiene definiciones de eventos y delegados. La relación entre eventos y delegados también se define en este objeto. Los objetos de la clase publicador (publisher) invocan este evento y notifican a otros objetos.

Suscriptor(subscriptor)- Es un objeto que acepta eventos y proporciona métodos de tratamiento de eventos. En la clase publicadora, se llama al método (método de tratamiento de eventos) de la clase suscriptora (suscriptora).

Declarar el evento

Se puede declarar un evento en dos pasos:

  1. Declarar el delegado

  2. Declarar una variable de delegado utilizando la palabra clave event

El siguiente ejemplo muestra cómo declarar un evento en la clase publicadora.

public delegate void Notify();  // Delegado
                    
public class ProcessBusinessLogic
{
    public event Notify ProcessCompleted; // Evento
}

En el ejemplo anterior, declaramos un delegado Notify y luego declaramos el evento ProcessCompleted del tipo de delegado Notify en la clase ProcessBusinessLogic. Por lo tanto, la clase ProcessBusinessLogic se llama publicador (publicador). El delegado Notify especifica la firma del método de tratamiento de eventos del evento ProcessCompleted. Especifica que el método de tratamiento de eventos de la clase suscriptora (suscriptora) debe tener el tipo de retorno void y no tener parámetros.

Ahora, veamos cómo desencadenamos el evento ProcessCompleted. Vea la siguiente implementación.

public delegate void Notify();  // Delegado
                    
public class ProcessBusinessLogic
{
    public event Notify ProcessCompleted; // Evento
    public void StartProcess()
    {
        Console.WriteLine("Process Started!");
        // Algunos códigos aquí...
        OnProcessCompleted();
    }
    protected virtual void OnProcessCompleted() //Método virtual protegido
    {
        //Si ProcessCompleted no es nulo, se llama al delegado
        ProcessCompleted?.Invoke(); 
    }
}

Arriba, el método StartProcess() llama al método onProcessCompleted() al final, lo que desencadenará un evento. Generalmente, para desencadenar un evento, se debe definir un método protegido y virtual con el nombre en <EventName>. El modificador protegido y virtual permite que las clases derivadas sobrescriban la lógica de desencadenamiento de eventos. Sin embargo, las clases derivadas deben llamar siempre al método On<EventName> de la clase base para asegurarse de que los delegados registrados reciban el evento.

El método OnProcessCompleted() utiliza ProcessCompleted?. invoke() para llamar al delegado. Esto llamará a todos los métodos de tratamiento de eventos registrados en el evento ProcessCompleted.

La clase suscriptora debe registrarse en el evento ProcessCompleted y manejarlo con un método que coincida con la firma del delegado Notify, como se muestra a continuación.

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // Registrar eventos
        bl.StartProcess();
    }
    // Gestor de eventos
    public static void bl_ProcessCompleted()
    {
        Console.WriteLine("Proceso Completado!");
    }
}

arriba, la clase Program es ProcessCompleted Suscriptores de eventos. Usa + = Operador para registrar eventos. Recuerde, esto es lo mismo que agregar métodos a la lista de invocación de un delegado de multicasting. El método bl_processcompleted () maneja el evento porque coincide con la firma del delegado Notify.

Delegado EventHandler integrado

.NET Framework contiene tipos de delegados integrados para eventos comunes, como EventHandler y EventHandler <TEventArgs>. Normalmente, cualquier evento debe incluir dos parámetros: la fuente del evento y los datos del evento. Para todos los eventos que no contienen datos de eventos, se debe usar el delegado EventHandler. Para los eventos que contienen datos que se deben enviar al procesador, se debe usar el delegado EventHandler<TEventArgs>.

El ejemplo mostrado puede usar el delegado EventHandler sin necesidad de declarar un delegado Notify personalizado, como se muestra a continuación.

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // Registro de eventos
        bl.StartProcess();
    }
    // Manejo de eventos
    public static void bl_ProcessCompleted(object sender, EventArgs e)
    {
        Console.WriteLine("Proceso Completado!");
    }
}
public class ProcessBusinessLogic
{
    // Declarar eventos utilizando EventHandler integrado
    public event EventHandler ProcessCompleted; 
    public void StartProcess()
    {
        Console.WriteLine("Process Started!");
        // Algunos códigos aquí...
        OnProcessCompleted(EventArgs.Empty); //No hay datos de eventos
    }
    protected virtual void OnProcessCompleted(EventArgs e)
    {
        ProcessCompleted?.Invoke(this, e);
    }
}

En el ejemplo anterior, el método del gestor de eventos bl_ProcessCompleted() contiene dos parámetros que coinciden con el delegado EventHandler. Al mismo tiempo, se pasa this como emisor y EventArgs. Cuando usamos Invoke() para desencadenar el evento en el método OnProcessCompleted(), es nulo. Porque nuestro evento no necesita ningún dato, solo notifica a los suscriptores que el proceso se ha completado, por lo que pasamos EventArgs.Empty.

Transmitir datos de evento

La mayoría de los eventos envían algunos datos a los suscriptores. La clase EventArgs es la clase base de todas las clases de datos de eventos. .NET contiene muchas clases de datos de eventos integradas, como SerialDataReceivedEventArgs. Sigue el patrón de nombre con EventArgs al final de todas las clases de datos de eventos. Puede derivar la clase EventArgs para crear clases de datos de eventos personalizados.

Transmita datos a los procesadores utilizando EventHandler <TEventArgs>, como se muestra a continuación.

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // Registro de eventos
        bl.StartProcess();
    }
    // Manejo de eventos
    public static void bl_ProcessCompleted(object sender, bool IsSuccessful)
    {
        Console.WriteLine("Process " + (IsSuccessful ? "Completed Successfully" : "failed");
    }
}
public class ProcessBusinessLogic
{
    // Declarar eventos utilizando EventHandler integrado
    public event EventHandler<bool> ProcessCompleted; 
    public void StartProcess()
    {
        try
        {
            Console.WriteLine("Process Started!");
            // Algunos códigos aquí...
            OnProcessCompleted(true);
        }
        catch(Exception ex)
        {
            OnProcessCompleted(false);
        }
    }
    protected virtual void OnProcessCompleted(bool IsSuccessful)
    {
        ProcessCompleted?.Invoke(this, IsSuccessful);
    }
}

En el ejemplo anterior, transmitimos un valor booleano único al procesador para indicar si el proceso se completó con éxito.

Si desea transmitir varios valores como datos de evento, puede crear una clase derivada de la clase base EventArgs, como se muestra a continuación.

class ProcessEventArgs : EventArgs
{
    public bool IsSuccessful { get; set; }
    public DateTime CompletionTime { get; set; }
}

A continuación, se muestra un ejemplo de cómo transmitir la clase ProcessEventArgs personalizada a los procesadores.

class Program
{
    public static void Main()
    {
        ProcessBusinessLogic bl = new ProcessBusinessLogic();
        bl.ProcessCompleted += bl_ProcessCompleted; // Registro de eventos
        bl.StartProcess();
    }
    // Manejo de eventos
    public static void bl_ProcessCompleted(object sender, ProcessEventArgs e)
    {
        Console.WriteLine("Process " + (e.IsSuccessful ? "Completed Successfully" : "failed"));
        Console.WriteLine("Completion Time: " + e.CompletionTime.ToLongDateString());
    }
}
public class ProcessBusinessLogic
{
    // Declarar eventos utilizando EventHandler integrado
    public event EventHandler<ProcessEventArgs> ProcessCompleted; 
    public void StartProcess()
    {
        var data = new ProcessEventArgs();
        try
        {
            Console.WriteLine("Process Started!");
            // Algunos códigos aquí...
            
            data.IsSuccessful = true;
            data.CompletionTime = DateTime.Now;
            OnProcessCompleted(data);
        }
        catch(Exception ex)
        {
            data.IsSuccessful = false;
            data.CompletionTime = DateTime.Now;
            OnProcessCompleted(data);
        }
    }
    protected virtual void OnProcessCompleted(ProcessEventArgs e)
    {
        ProcessCompleted?.Invoke(this, e);
    }
}

Por lo tanto, puede crear, lanzar, registrar y manejar eventos en C#.

Puntos a recordar

  1. Los eventos son envolturas de delegados. Esto depende del delegado.

  2. Utilice la palabra clave 'event' junto con la variable de tipo delegado para declarar eventos.

  3. Utilice el delegado integradoEventHandler oEventHandler <TEventArgs> se utiliza para eventos comunes.

  4. El emisor de eventos lanza un evento, mientras que el suscriptor de eventos se registra en un evento y proporciona un método de manejo de eventos.

  5. Nombra el método que dispara el evento con el nombre del evento, que debe comenzar con 'On'.

  6. La firma del método del gestor debe coincidir con la firma del delegado.

  7. Usar+ El operador = registra eventos. Usar -El operador = cancela la suscripción, no se puede usar el operador =.

  8. Transmitir datos de eventos usando EventHandler <TEventArgs>.

  9. Heredar de la clase base EventArgs para crear una clase de datos de eventos personalizados.

  10. Se puede declarar un evento como estático, virtual, sellado y abstracto (static, virtual, sealed, abstract).

  11. Una interfaz puede contener eventos como miembros.

  12. Si hay varios suscriptores, se llamará al gestor de eventos en synchronización.