C# Eventos (Event)
Los eventos (Event) de C# son miembros utilizados para enviar notificaciones de eventos específicos a los suscriptores. Los eventos se utilizan comúnmente para implementar el patrón observador, que permite que un objeto notifique a otros objetos sobre cambios de estado sin necesidad de conocer los detalles de esos objetos.
Evento (Event)Básicamente es una operación del usuario, como pulsar una tecla, hacer clic, mover el mouse, etc., o alguna información de aviso, como notificaciones generadas por el sistema. Las aplicaciones deben responder a los eventos cuando estos ocurren. Por ejemplo, las interrupciones.
En C#, se utiliza el mecanismo de eventos para implementar la comunicación entre subprocesos.
Puntos clave:
- Declarar delegado: Defina el tipo de delegado que usará el evento. Un delegado es una firma de función.
- Declarar evento: Usar la
eventpalabra clave para declarar un evento. - Desencadenar evento: Llame al evento en el momento adecuado para notificar a todos los suscriptores.
- Suscribirse y cancelar la suscripción a eventos: Otras clases pueden usar el
+=y-=operador para suscribirse y cancelar la suscripción a eventos.
Uso de delegados mediante eventos
Los eventos se declaran y se generan en una clase, y se asocian con los manejadores de eventos mediante delegados en la misma clase u otras clases. La clase que contiene el evento se utiliza para publicar el evento. Esto se llama laclase publicadora (publisher). Las otras clases que aceptan el evento se denominanclase suscriptora (subscriber). Los eventos utilizan elmodelo publicador-suscriptor (publisher-subscriber).
El publicador (publisher)es un objeto que contiene definiciones de eventos y delegados. La conexión entre el evento y el delegado también se define en este objeto. Los objetos de la clase publicadora (publisher) llaman a este evento y notifican a otros objetos.
El suscriptor (subscriber)es un objeto que acepta eventos y proporciona manejadores de eventos. El delegado en la clase publicadora (publisher) llama a los métodos (manejadores de eventos) en la clase suscriptora (subscriber).
Declarar eventos (Event)
Para declarar un evento dentro de una clase, primero debe declarar el tipo de delegado para el evento. Por ejemplo:
public delegate void BoilerLogHandler(string status);
Luego, declare el evento en sí, usando laeventpalabra clave:
// 基于上面的委托定义事件 public event BoilerLogHandler BoilerEventLog;
El código anterior define un delegado llamadoBoilerLogHandlery un evento llamadoBoilerEventLog. El evento llamará al delegado cuando se genere.
El siguiente ejemplo muestra cómo usar eventos en C#:
Ejemplo
namespace EventDemo
{
// Definir un tipo de delegado para el manejador de eventos
public delegate void NotifyEventHandler(object sender, EventArgs e);
// Clase publicadora
public class ProcessBusinessLogic
{
// Declarar evento
public event NotifyEventHandler ProcessCompleted;
// Método para desencadenar el evento
protected virtual void OnProcessCompleted(EventArgs e)
{
ProcessCompleted?.Invoke(this, e);
}
// Simular el proceso de lógica de negocio y desencadenar el evento
public void StartProcess()
{
Console.WriteLine("Process Started!");
// Aquí se puede agregar la lógica de negocio real
// Lógica de negocio completada, desencadenar el evento
OnProcessCompleted(EventArgs.Empty);
}
}
// Clase suscriptora
public class EventSubscriber
{
public void Subscribe(ProcessBusinessLogic process)
{
process.ProcessCompleted += Process_ProcessCompleted;
}
private void Process_ProcessCompleted(object sender, EventArgs e)
{
Console.WriteLine("Process Completed!");
}
}
class Program
{
static void Main(string[] args)
{
ProcessBusinessLogic process = new ProcessBusinessLogic();
EventSubscriber subscriber = new EventSubscriber();
// Suscribirse al evento
subscriber.Subscribe(process);
// Iniciar el proceso
process.StartProcess();
Console.ReadLine();
}
}
}
Explicación
1. Definir el tipo de delegado:
public delegate void NotifyEventHandler(object sender, EventArgs e);
Este es un tipo de delegado que define la firma del manejador de eventos. Normalmente se usaEventHandleroEventHandler<TEventArgs>para reemplazar los delegados personalizados.
2. Declarar el evento:
public event NotifyEventHandler ProcessCompleted;
Este es un evento que utiliza el tipo de delegado NotifyEventHandler.
3. Desencadenar el evento:
protected virtual void OnProcessCompleted(EventArgs e)
{
ProcessCompleted?.Invoke(this, e);
}Este es un método protegido utilizado para desencadenar el evento. Utilice la?.Invokesintaxis para asegurar que el evento solo se llame cuando haya suscriptores.
4. Suscribirse y cancelar la suscripción a eventos:
process.ProcessCompleted += Process_ProcessCompleted;
Los suscriptores usan el+=operador para suscribirse a eventos y definir el manejador de eventosProcess_ProcessCompleted。
Ejemplo
Ejemplo 1
namespace SimpleEvent
{
using System;
/*********** Clase publicadora ***********/
public class EventTest
{
private int value;
public delegate void NumManipulationHandler();
public event NumManipulationHandler ChangeNum;
protected virtual void OnNumChanged()
{
if ( ChangeNum != null )
{
ChangeNum(); /* Evento desencadenado */
}else {
Console.WriteLine( "event not fire" );
Console.ReadKey(); /* Presione Enter para continuar */
}
}
public EventTest()
{
int n = 5;
SetValue( n );
}
public void SetValue( int n )
{
if ( value != n )
{
value = n;
OnNumChanged();
}
}
}
/*********** Clase suscriptora ***********/
public class subscribEvent
{
public void printf()
{
Console.WriteLine( "event fire" );
Console.ReadKey(); /* Presione Enter para continuar */
}
}
/*********** Desencadenar ***********/
public class MainClass
{
public static void Main()
{
EventTest e = new EventTest(); /* Crear una instancia del objeto, la primera vez no se desencadena ningún evento */
subscribEvent v = new subscribEvent(); /* Crear una instancia del objeto */
e.ChangeNum += new EventTest.NumManipulationHandler( v.printf ); /* Registrar */
e.SetValue( 7 );
e.SetValue( 11 );
}
}
}
Cuando el código anterior se compila y ejecuta, produce los siguientes resultados:
event not fire event fire event fire
Este ejemplo proporciona una aplicación simple para la resolución de problemas de un sistema de caldera de agua caliente. Cuando el ingeniero de mantenimiento inspecciona la caldera, la temperatura y la presión de la caldera se registran automáticamente en un archivo de registro junto con las observaciones del ingeniero de mantenimiento.
Ejemplo 2
using System.IO;
namespace BoilerEventAppl
{
// Clase Boiler
class Boiler
{
public int Temp { get; private set; }
public int Pressure { get; private set; }
public Boiler(int temp, int pressure)
{
Temp = temp;
Pressure = pressure;
}
}
// Publicador de eventos
class DelegateBoilerEvent
{
public delegate void BoilerLogHandler(string status);
// Definir evento basado en el delegado anterior
public event BoilerLogHandler BoilerEventLog;
public void LogProcess()
{
string remarks = "O.K.";
Boiler boiler = new Boiler(100, 12);
int temp = boiler.Temp;
int pressure = boiler.Pressure;
if (temp > 150 || temp < 80 || pressure < 12 || pressure > 15)
{
remarks = "Need Maintenance";
}
OnBoilerEventLog($"Logging Info:\nTemperature: {temp}\nPressure: {pressure}\nMessage: {remarks}");
}
protected void OnBoilerEventLog(string message)
{
BoilerEventLog?.Invoke(message);
}
}
// Esta clase conserva las condiciones para escribir en el archivo de registro
class BoilerInfoLogger : IDisposable
{
private readonly StreamWriter _streamWriter;
public BoilerInfoLogger(string filename)
{
_streamWriter = new StreamWriter(new FileStream(filename, FileMode.Append, FileAccess.Write));
}
public void Logger(string info)
{
_streamWriter.WriteLine(info);
}
public void Dispose()
{
_streamWriter?.Close();
}
}
// Suscriptor de eventos
public class RecordBoilerInfo
{
static void Logger(string info)
{
Console.WriteLine(info);
}
static void Main(string[] args)
{
using (BoilerInfoLogger fileLogger = new BoilerInfoLogger("e:\\boiler.txt"))
{
DelegateBoilerEvent boilerEvent = new DelegateBoilerEvent();
boilerEvent.BoilerEventLog += Logger;
boilerEvent.BoilerEventLog += fileLogger.Logger;
boilerEvent.LogProcess();
}
Console.ReadLine();
}
}
}
Cuando el código anterior se compila y ejecuta, produce los siguientes resultados:
Logging info: Temperature 100 Pressure 12 Message: O. KOtras extensiones