2013-08-11 20 views
18

Chcę powiadomić wiadomość alarmową do wszystkich subskrybentów, gdy wystąpi pułapka.C# delegate vs.s. eventHandler

Kod, który napisałem, działa dobrze dzięki metodzie delegatów (myDelegate del).

moje pytania są ..

  1. Chcę wiedzieć, czy warto za pomocą eventhandler lepiej delegata? nie wiesz, co różni się między delegatem a wydarzeniem dokładnie w moim przypadku?

  2. notify (trapinfo t), to właśnie zrobiłem tutaj, aby uzyskać informacje o pułapce. Ale nie wydaje się to dobrym pomysłem. Zapoznaj się z lekcją samouczka online wprowadzającą przekazujący obiekt delegatów, czy jest to właściwe dla mojej sprawy? I jak mam to zrobić? Jakieś sugestie?

Thanks a lot :)

Mój kod:

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

Aktualizacja 2013-08-12

Jak o obserwatora/obserwowalne wzorzec projektowy, który wygląda świetne w moim przypadku. (EventHandler) Super-simple example of C# observer/observable with delegates

W moim przypadku maszyna subskrybuje komunikator pułapki. (Dodaj maszynę do listy wywołań) Po pojawieniu się pułapki wyślij wiadomość do wszystkich subskrybowanych komputerów. (Call handleEvent go obsłużyć)

Zaleta:

  • nie obchodzi GetInvocationList() już, wystarczy użyć (+ =) i (- =), aby zdecydować, które wysyłają pułapka.

  • Łatwo zrozumieć logikę mojego programu.

Wiem, że byłoby na to kilka sposobów, ale chciałbym móc przeanalizować jego zalety i wady. Dzięki za komentarze i sugestie, byłoby to bardzo pomocne!

czytam MSDN EventArgs artykuł który Matthew Watson sugeruje system.eventargs

oto moja wersja wydarzeń:

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

możliwe duplikat [Zrozumienie imprez i obsługi zdarzeń w języku C#] (http://stackoverflow.com/questions/803242/understanding-events-and-event-handlers-in-c-sharp) –

Odpowiedz

16

Różnica między zdarzeniem a delegatem jest to, że:

deklaracja zdarzenie dodaje warstwę ochronną na przykład pełnomocnik. Ochrona ta uniemożliwia klientom delegata z resetowania delegata i jego listy wywołania, a jedynie umożliwia dodawanie lub usuwanie cele z listy wywołania

Zobacz What are the differences between delegates and events?

2), jak widzę, abonent powinien nie zmieniaj swobodnie delegata.Jeden subskrybent może przypisać "=" zamiast dodawać "+ =". Przypisuje nowego delegata, dlatego poprzedni delegat z listą wywołań zostanie utracony, a poprzedni abonenci nie będą już wywoływani. Dlatego na pewno powinieneś używać Eventu. lub możesz zmienić swój kod, aby uczynić swojego delegata prywatnym i napisać dodatkowe funkcje do manipulowania nim. tak będzie to twoje własne zachowanie zdarzenia.

//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

Muszę więc zająć się listą inwokacji w moim opublikowanym kodzie, prawda? –

+0

Musisz podać funkcje do zmiany, zamiast udostępniać go bezpośrednio. Koncepcja hermetyzacjiOOP – qwr

+0

Dzięki, rozumiem :) –

8

jest znacznie lepiej użyć event dla przykładu.

  • event jest rozumiane przez Visual Studio Form i projektantów WPF, dzięki czemu można używać IDE do subskrypcji zdarzeń.

  • Podczas podnoszenia numeru events nie trzeba pisać własnych instrukcji obsługi, aby je przeglądać.

  • events to sposób, w jaki większość programistów oczekuje dostępu do tej funkcji.

  • Jeśli użyjesz delegata, zużywający się kod może zepsuć się z nim w sposób, który chcesz zablokować (np. Zresetować listę wywołań). events nie dopuść do tego.

Co do drugiego pytania: Użycie event by utworzyć klasę pochodną od EventArgs do przechowywania danych i przekazać, że do zdarzenia, gdy go podnieść. Konsument będzie miał do niego dostęp.

Zobacz tutaj szczegóły: http://msdn.microsoft.com/en-us/library/system.eventargs.aspx

+0

podziękowania zaktualizowałem swój kod po przeczytaniu msdn, który podałeś :) –