example evento event declarar custom crear and c# delegates event-handling observer-pattern

c# - evento - eventhandler<>



C#delegate vs eventHandler (2)

Quiero notificar un mensaje de alerta a los suscriptores cuando se produce una trampa.

El código que hice funciona bien a través de un método de delegado (myDelegate del).

mis preguntas son ...

  1. Quiero saber si vale la pena usar Eventhandler mejor delegado? ¿No estoy seguro de qué hay de diferente entre delegado y evento exactamente en mi caso?

  2. Notificar (trapinfo t), eso es lo que he hecho aquí, para obtener información de la trampa. Pero no parece ser una buena idea. Lea algunas lecciones tutoriales en línea que presentan el objeto de los delegados que pasan, ¿es apropiado para mi caso? Y como debo hacer? ¿Alguna sugerencia?

Muchas gracias :)

Mi código:

public class trapinfo { public string info; public string ip; public string cause; } public class trap { public delegate void myDelegate(trapinfo t); public myDelegate del; trapinfo info = new trapinfo(); public void run() { //While(true) // If a trap occurred, notify the subscriber for (; ; ) { Thread.Sleep(500); foreach (myDelegate d in del.GetInvocationList()) { info.cause = "Shut Down"; info.ip = "192.168.0.1"; info.info = "Test"; d.Invoke(info); } } } } public class machine { private int _occuredtime=0; public trapinfo info = new trapinfo(); public void notify(trapinfo t) { ++_occuredtime; info.cause = t.cause; info.info = t.info; info.ip = t.ip; getInfo(); } public void subscribe(trap t) { t.del += new trap.myDelegate(notify); } public void getInfo() { Console.WriteLine("<Alert>: cauese/{0}, info/ {1}, ip/{2}, time/{3}", info.cause, info.info, info.ip,_occuredtime); } } class Program { static void Main(string[] args) { trap t = new trap(); machine machineA = new machine(); machineA.subscribe(t); t.run(); } }

Actualización 2013-08-12

¿Qué tal el patrón de diseño observador / observable, que se ve muy bien en mi caso? (EventHandler) Ejemplo súper simple de C # observador / observable con delegados

En mi caso, una máquina suscribe una trampa de messenger. (Agregar máquina a una lista de invocación) Una vez que se produce una captura, envíe un mensaje a todas las máquinas que están suscritas. (Llame a HandleEvent para manejarlo)

Ventaja:

  • Ya no importa GetInvocationList (), solo use (+ =) y (- =) para decidir a quién enviar trampa.

  • Fácil de entender la lógica de mi programa.

Sé que habría varias formas de hacerlo, pero me gustaría poder analizar sus pros y sus contras. Y gracias por sus comentarios y sugerencias, ¡eso sería muy útil!

Leí el artículo de MSDN EventArgs que Matthew Watson sugiere system.eventargs

Aquí está mi versión del evento:

public class TrapInfoEventArgs : EventArgs { public int info { get; set; } public string ip { get; set; } public string cause { get; set; } } public class trap { public event EventHandler<TrapInfoEventArgs> TrapOccurred; protected virtual void OnTrapOccurred(TrapInfoEventArgs e) { EventHandler<TrapInfoEventArgs> handler = TrapOccurred; if (handler != null) { handler(this, e); } } public void run() { //While(true) // If a trap occurred, notify the subscriber for (; ; ) { Thread.Sleep(500); TrapInfoEventArgs args = new TrapInfoEventArgs(); args.cause = "Shut Down"; OnTrapOccurred(args); } } } public class machine { public void c_TrapOccurred(object sender, TrapInfoEventArgs e) { Console.WriteLine("<Alert>: cauese/{0}, info/ {1}, ip/{2}, time/{3}", e.cause, e.info, e.ip, DateTime.Now.ToString()); } } class Program { static void Main(string[] args) { trap t = new trap(); machine machineA = new machine(); t.TrapOccurred += machineA.c_TrapOccurred; //notify machine A t.run(); } }


Es mucho mejor usar un event para su ejemplo.

  • Los diseñadores de Visual Studio Form y WPF entienden un event , por lo que puede utilizar el IDE para suscribirse a eventos.

  • Al generar events , no es necesario que escriba su propio manejo de foreach para recorrerlos.

  • events son la forma en que la mayoría de los programadores esperan que se acceda a esta funcionalidad.

  • Si utiliza un delegado, el código que lo consume puede alterarlo de una manera que usted querrá evitar (como restablecer su lista de invocaciones). events no permiten que eso suceda.

En cuanto a su segunda pregunta: al usar un event , crearía una clase derivada de EventArgs para retener los datos y pasarla al evento cuando la genere. El consumidor tendrá acceso a él.

Consulte aquí para obtener más información: system.eventargs


La diferencia entre evento y delegado es que:

La declaración de evento agrega una capa de protección en la instancia de delegado. Esta protección evita que los clientes del delegado restablezcan el delegado y su lista de invocación, y solo permite agregar o eliminar objetivos de la lista de invocación

Ver ¿Cuáles son las diferencias entre delegados y eventos?

2) Como veo, su suscriptor no debe cambiar el delegado libremente. Un suscriptor puede asignarlo "=" en lugar de agregar "+ =". Esto asignará un nuevo delegado, por lo tanto, el delegado anterior con su lista de invocación se perderá y los suscriptores anteriores ya no se llama Así que deberías usar el evento seguro. o puede cambiar su código para hacer que su delegado sea privado y escribir funciones adicionales para manipularlo. Así será su propio comportamiento de evento.

//preventing direct assignment private myDelegate del ; public void AddCallback(myDelegate m){ del += m; } public void RemoveCallback(myDelegate m){ del -= m; } //or public static trap operator +(trap x,myDelegate m){ x.AddCallback(m); return x; } public static trap operator -(trap x, myDelegate m) { x.RemoveCallback(m); return x; } //usage //t.AddCallback(new trap.myDelegate(notify)); t+=new trap.myDelegate(notify);