2013-08-11 30 views
18

Desidero comunicare un messaggio di avviso a tutti i sottoscrittori in caso di trap.C# delegato v.s. eventHandler

Il codice che ho eseguito funziona correttamente con un metodo delegato (myDelegate del).

le mie domande sono ..

  1. che voglio sapere è la pena usare EventHandler meglio delegato? non è sicuro che cosa c'è di diverso tra delegato ed evento esattamente nel mio caso?

  2. notifica (trapinfo t), questo è quello che ho fatto qui, per ottenere informazioni sulla trappola. Ma sembra non essere una buona idea. Leggi alcune lezioni di tutorial online che introducono l'oggetto dei delegati di passaggio, è appropriato per il mio caso? E come dovrei fare? Eventuali suggerimenti?

Grazie mille :)

Il mio codice:

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(); 
     } 
    } 

Aggiornamento 2013-08-12

ne dite di osservatore/design pattern osservabili, che sembra ottimo per il mio caso. (EventHandler) Super-simple example of C# observer/observable with delegates

Nel mio caso, una macchina sottoscrive un trap Messenger. (Aggiungi macchina a un elenco di chiamate) Una volta verificata una trap, invia un messaggio a tutte le macchine che sono iscritte. (Chiamata handleEvent gestirlo)

Vantaggio:

  • non si preoccupano GetInvocationList() più, basta usare (+ =) e (- =) per decidere chi trappola di invio a.

  • Facile capire la logica del mio programma.

So che ci sarebbero diversi modi per farlo, ma vorrei poterne analizzare i pro ei contro. E grazie per i vostri commenti e suggerimenti, sarebbe molto utile!

ho letto MSDN EventArgs articolo che Matthew Watson suggerisce system.eventargs

Ecco il mio evento Versione:

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(); 
    } 
} 
+0

possibile duplicato del [eventi comprensione e gestori di eventi in C#] (http://stackoverflow.com/questions/803242/understanding-events-and-event-handlers-in-c-sharp) –

risposta

16

La differenza tra evento e delegato è che:

dichiarazione di evento aggiunge uno strato di protezione per l'istanza delegato. Questa protezione impedisce i clienti del delegato dal reset del delegato e la sua lista invocazione, e consente solo di aggiungere o rimuovere bersagli dalla lista invocazione

Vedi What are the differences between delegates and events?

2) Come vedo il vostro abbonato dovrebbe non cambiare delegato liberamente. Un abbonato può assegnare "=" invece di aggiungere "+ =". Questo assegnerà un nuovo delegato, pertanto, il delegato precedente con la sua lista di invocazione andrà perso e gli iscritti precedenti non chiameranno più. Quindi dovresti usare Evento di sicuro. oppure puoi cambiare il tuo codice per rendere privato il tuo delegato e scrivere funzioni aggiuntive per manipolarlo. Quindi sarà il tuo comportamento personale.

//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); 
+0

Quindi devo occuparmi dell'elenco di invocazioni nel mio codice postato, vero? –

+0

è necessario fornire funzioni per cambiarlo invece di renderlo accessibile direttamente. Concetto di incapsulamento OPP – qwr

+0

Grazie, ho capito :) –

8

E 'molto meglio utilizzare un event per il vostro esempio.

  • Un event è capito dal modulo di Visual Studio e designer WPF, in modo da poter utilizzare l'IDE per sottoscrivere gli eventi.

  • Quando si alza events, non è necessario scrivere la propria manipolazione foreach per eseguirne l'iterazione.

  • events sono il modo in cui la maggior parte dei programmatori prevede l'accesso a questa funzionalità.

  • Se si utilizza un delegato, il codice che consuma può interferire con esso nei modi che si desidera impedire (ad esempio reimpostare l'elenco di chiamate). events non permettere che ciò accada.

Per quanto riguarda la seconda domanda: L'utilizzo di un event si creerebbe una classe derivata da EventArgs per contenere i dati, e passare che per l'evento quando si sollevano esso. Il consumatore avrà quindi accesso ad esso.

Vedi qui per i dettagli: http://msdn.microsoft.com/en-us/library/system.eventargs.aspx

+0

grazie, ho aggiornato il mio codice dopo aver letto msdn che hai fornito :) –