Frage

Ich habe derzeit ein Verständnis und Ereignisse hardtime in C # Umsetzung Kongressteilnehmer verwenden. Ich bin auf die Java Art und Weise verwendet, Dinge zu tun:

  1. Definieren Sie eine Schnittstelle für einen Hörer-Typ, die eine Anzahl von Methodendefinitionen enthalten würde
  2. definieren Adapterklasse für die Schnittstelle die Dinge zu erleichtern, wenn ich in all den Ereignissen in einem Zuhörer definiert interessiert mich nicht
  3. Define Hinzufügen, Entfernen und Erhalten [] Methoden in der Klasse, die die Ereignisse
  4. wirft
  5. geschützt Feuer Methoden definieren, die schmutzige Arbeit der Schleife durch die Liste der hinzugefügten Hörer und rief die richtige Methode
  6. zu tun

Das verstehe ich (und wie!) - ich weiß, dass ich in c # das gleiche dies genau tun könnte, aber es scheint, dass ein neues (bessere?) System für C # ist. unzählige Tutorials Nach dem Lesen der Verwendung von Delegierten und Ereignissen in c # zu erklären bin ich immer noch nicht näher wirklich zu verstehen, was los ist: S


Kurz gesagt, für die folgenden Methoden, wie würde ich das Ereignissystem in c # implementieren:

void computerStarted(Computer computer);
void computerStopped(Computer computer);
void computerReset(Computer computer);
void computerError(Computer computer, Exception error);

^ Die obigen Verfahren werden aus einer Java-Anwendung genommen, die ich einmal gemacht, die ich in dem Hafen bin versucht, über zu c #.

Vielen vielen Dank!

War es hilfreich?

Lösung

Sie würden vier Ereignisse erstellen und Methoden, um sie zu erhöhen, zusammen mit einer neuen EventArgs-basierten Klasse um den Fehler anzuzeigen:

public class ExceptionEventArgs : EventArgs
{
    private readonly Exception error;

    public ExceptionEventArgs(Exception error)
    {
         this.error = error;
    }

    public Error
    {
         get { return error; }
    }
}

public class Computer
{
    public event EventHandler Started = delegate{};
    public event EventHandler Stopped = delegate{};
    public event EventHandler Reset = delegate{};
    public event EventHandler<ExceptionEventArgs> Error = delegate{};

    protected void OnStarted()
    {
        Started(this, EventArgs.Empty);
    }

    protected void OnStopped()
    {
        Stopped(this, EventArgs.Empty);
    }

    protected void OnReset()
    {
        Reset(this, EventArgs.Empty);
    }

    protected void OnError(Exception e)
    {
        Error(this, new ExceptionEventArgs(e));
    }
}

Klassen würden dann auf das Ereignis abonnieren entweder ein Verfahren oder eine anonyme Funktion:

someComputer.Started += StartEventHandler; // A method
someComputer.Stopped += delegate(object o, EventArgs e)
{ 
    Console.WriteLine("{0} has started", o);
};
someComputer.Reset += (o, e) => Console.WriteLine("{0} has been reset");

Ein paar Dinge zu beachten, über die oben:

  • Die OnXXX Methoden sind geschützt, so dass abgeleitete Klassen, die Ereignisse auslösen können. Dies ist nicht immer notwendig -. Tun es, wie Sie sehen, passen
  • Das delegate{} Stück auf jeder Veranstaltung Erklärung ist nur ein Trick, um eine NULL-Prüfung zu tun, um zu vermeiden. Es ist Ihre Anmeldung eine no-op-Ereignishandler zu jedem Ereignis
  • Die Ereignismeldungen sind feldartigen Ereignisse . Was wird tatsächlich erstellt ist sowohl eine Variable und ein Ereignis. Innerhalb der Klasse sehen Sie die Variable; außerhalb der Klasse sehen Sie das Ereignis.

Sehen Sie mein events / Delegierten Artikel für viel mehr Details über die Ereignisse.

Andere Tipps

Sie werden einen einzigen Delegierten dafür definieren müssen

public delegate void ComputerEvent(object sender, ComputerEventArgs e);

ComputerEventArgs würde wie folgt definiert werden:

public class ComputerEventArgs : EventArgs
{
    // TODO wrap in properties
    public Computer computer;
    public Exception error;

    public ComputerEventArgs(Computer aComputer, Exception anError)
    {
        computer = aComputer;
        error = anError;
    }

    public ComputerEventArgs(Computer aComputer) : this(aComputer, null)
    {
    }
}

Die Klasse, die die Ereignisse ausgelöst würde diese:

public YourClass
{
    ...
    public event ComputerEvent ComputerStarted;
    public event ComputerEvent ComputerStopped;
    public event ComputerEvent ComputerReset;
    public event ComputerEvent ComputerError;
    ...
}

Dies ist, wie Sie Handler zu den Ereignissen zuordnen:

YourClass obj = new YourClass();
obj.ComputerStarted += new ComputerEvent(your_computer_started_handler);

Der Handler ist:

private void ComputerStartedEventHandler(object sender, ComputerEventArgs e)
{
   // do your thing.
}

Der wesentliche Unterschied besteht darin, dass die Ereignisse in C # nicht-Schnittstelle basiert. Stattdessen erklärt die Veranstaltung Verlag die Delegierten, die Sie als Funktionszeiger denken können (wenn auch nicht genau gleich :-)). Der Teilnehmer dann implementiert das Ereignis Prototyp als reguläres Verfahren und fügt eine neue Instanz des Delegaten an der Event-Handler-Kette des Herausgebers. Lesen Sie mehr über Delegierten und Veranstaltungen .

Sie können auch kurzen Vergleich von C # vs. Java Ereignissen hier lesen .

Zunächst einmal gibt es eine Standardmethode Signatur in .Net, die typischerweise für Veranstaltungen genutzt wird. Die Sprachen erlauben jede Art von Methodensignatur überhaupt für Veranstaltungen genutzt werden, und es gibt einige Experten, die die Konvention glauben ist fehlerhaft (ich meistens zustimmen), aber es ist, was es ist, und ich werde es in diesem Beispiel folgen.

  1. Erstellen Sie eine Klasse, die die Veranstaltungs-Parameter (abgeleitet von EventArgs) enthalten wird.
public class ComputerEventArgs : EventArgs 
{
  Computer computer; 
  // constructor, properties, etc.
}
  1. Erstellen Sie eine öffentliche Veranstaltung auf die Klasse, die das Ereignis ausgelöst wird.
    class ComputerEventGenerator  // I picked a terrible name BTW.
    {
      public event EventHandler<ComputerEventArgs> ComputerStarted;
      public event EventHandler<ComputerEventArgs> ComputerStopped;
      public event EventHandler<ComputerEventArgs> ComputerReset;
    ...
    }
  1. Rufen Sie die Ereignisse.
    class ComputerEventGenerator
    {
    ...
      private void OnComputerStarted(Computer computer) 
      {
        EventHandler<ComputerEventArgs> temp = ComputerStarted;
        if (temp != null) temp(this, new ComputerEventArgs(computer)); // replace "this" with null if the event is static
      }
     }
  1. Schließen Sie einen Handler für das Ereignis.
    void OnLoad()
    {
      ComputerEventGenerator computerEventGenerator = new ComputerEventGenerator();
      computerEventGenerator.ComputerStarted += new  EventHandler<ComputerEventArgs>(ComputerEventGenerator_ComputerStarted);
    }
  1. Erstellen Sie den Handler einfach angebracht (vor allem durch die Tab-Taste in VS drücken).
    private void ComputerEventGenerator_ComputerStarted(object sender, ComputerEventArgs args)
    {
      if (args.Computer.Name == "HAL9000")
         ShutItDownNow(args.Computer);
    }
  1. Vergessen Sie nicht, den Handler zu lösen, wenn Sie fertig sind. (Forgetting zu tun, ist dies die größte Quelle von Speicherlecks in C #!)
    void OnClose()
    {
      ComputerEventGenerator.ComputerStarted -= ComputerEventGenerator_ComputerStarted;
    }

Und das ist es!

EDIT: Ich kann ehrlich nicht, warum meine nummerierten Punkte alle als „1“ erscheinen Ich hasse Computer.

Es gibt mehrere Möglichkeiten, zu tun, was Sie wollen. Das direkte Weg wäre, die Delegierten in der Hosting-Klasse für jedes Ereignis zu definieren, z.

public delegate void ComputerStartedDelegate(Computer computer);
protected event ComputerStartedDelegate ComputerStarted;
public void OnComputerStarted(Computer computer)
{
    if (ComputerStarted != null)
    {
        ComputerStarted.Invoke(computer);
    }
}
protected void someMethod()
{
    //...
    computer.Started = true;  //or whatever
    OnComputerStarted(computer);
    //...
}

jedes Objekt kann ‚hören‘ für diese Veranstaltung einfach durch:

Computer comp = new Computer();
comp.ComputerStarted += new ComputerStartedDelegate(
    this.ComputerStartedHandler);

protected void ComputerStartedHandler(Computer computer)
{
    //do something
}

Die ‚empfohlene Standardmethode‘, dies zu tun wäre, eine Unterklasse von EventArgs zu definieren, den Computer (und alten / neuen Zustand und Ausnahme) Wert (e) zu halten, reduzierte 4 Delegierten ein. In diesem Fall, dass eine sauberere Lösung, besonders wäre. mit einem Enum für die Computer-Staaten im Fall einer späteren Erweiterung. Aber die grundlegende Technik bleibt das gleiche:

  • definiert die Delegierten die Signatur / Schnittstelle für den Event-Handler / Hörer
  • das Ereignisdatenelement eine Liste der ‚Hörer‘

Zuhörer werden abgenommen, mit der - = Syntax statt + =

In c # Veranstaltungen sind Teilnehmer. Sie verhalten sich in ähnlicher Weise auf einen Funktionszeiger in C / C ++, sind aber tatsächlich Klassen abgeleitet von System.Delegate.

In diesem Fall erstellen Sie eine benutzerdefinierte EventArgs Klasse das Computerobjekt zu übergeben.

public class ComputerEventArgs : EventArgs
{
  private Computer _computer;

  public ComputerEventArgs(Computer computer) {
    _computer = computer;
  }

  public Computer Computer { get { return _computer; } }
}

Dann setzen die Ereignisse vom Hersteller:

public class ComputerEventProducer
{
  public event EventHandler<ComputerEventArgs> Started;
  public event EventHandler<ComputerEventArgs> Stopped;
  public event EventHandler<ComputerEventArgs> Reset;
  public event EventHandler<ComputerEventArgs> Error;

  /*
  // Invokes the Started event */
  private void OnStarted(Computer computer) {
    if( Started != null ) {
      Started(this, new ComputerEventArgs(computer));
    }
  }

  // Add OnStopped, OnReset and OnError

}

Der Verbraucher der Ereignisse bindet dann einen Handler-Funktion an jedem Ereignis auf den Verbraucher.

public class ComputerEventConsumer
{
  public void ComputerEventConsumer(ComputerEventProducer producer) {
    producer.Started += new EventHandler<ComputerEventArgs>(ComputerStarted);
    // Add other event handlers
  }

  private void ComputerStarted(object sender, ComputerEventArgs e) {
  }
}

Wenn die ComputerEventProducer Anrufe OnStarted die Schritte Ereignis aufgerufen wird, die wiederum die ComputerEventConsumer.ComputerStarted Methode aufrufen.

Der Delegat deklariert eine Funktion Unterschrift, und wenn es als ein Ereignis für eine Klasse verwendet, ist es fungiert auch als eine Sammlung von eingetragen Rufzielen. Der + = und -. = Syntax auf ein Ereignis zum Hinzufügen eines Ziels zu der Liste verwendet wird

In Anbetracht der folgend Delegierten als Ereignisse verwendet:

// arguments for events
public class ComputerEventArgs : EventArgs
{
    public Computer Computer { get; set; }
}

public class ComputerErrorEventArgs : ComputerEventArgs
{
    public Exception Error  { get; set; }
}

// delegates for events
public delegate void ComputerEventHandler(object sender, ComputerEventArgs e);

public delegate void ComputerErrorEventHandler(object sender, ComputerErrorEventArgs e);

// component that raises events
public class Thing
{
    public event ComputerEventHandler Started;
    public event ComputerEventHandler Stopped;
    public event ComputerEventHandler Reset;
    public event ComputerErrorEventHandler Error;
}

Sie würden auf diese Ereignisse abonnieren mit dem folgenden:

class Program
{
    static void Main(string[] args)
    {
        var thing = new Thing();
        thing.Started += thing_Started;
    }

    static void thing_Started(object sender, ComputerEventArgs e)
    {
        throw new NotImplementedException();
    }
}

Auch wenn die Argumente könnte alles sein, das Objekt Absender und EventArgse ist eine Konvention, die sehr konsequent verwendet wird. Der + = thing_started wird zunächst eine Instanz des Delegaten Zeige Methode zum Ziel, dann fügen Sie es zu dem Ereignis.

Auf der Komponente selbst Sie Methoden der Regel hinzufügen, würden die Ereignisse Feuer:

public class Thing
{
    public event ComputerEventHandler Started;

    public void OnStarted(Computer computer)
    {
        if (Started != null)
            Started(this, new ComputerEventArgs {Computer = computer});
    }
}

Sie müssen für null im Falle testen keine Delegierten zum Ereignis hinzugefügt wurden. Wenn Sie den Methodenaufruf jedoch alle Teilnehmer machen die hinzugefügt wurden aufgerufen. Aus diesem Grund ist für Veranstaltungen der Rückgabetyp ungültig ist - es gibt keinen einzigen Wert -. So Informationen rückzukoppeln Sie Eigenschaften auf die EventArgs haben würde, die die Ereignishandler ändern würde

Eine weitere Verfeinerung wäre die allgemeine Eventhandler Delegaten zu verwenden, anstatt einen konkreten Delegierten für jede Art von args erklärt.

public class Thing
{
    public event EventHandler<ComputerEventArgs> Started;
    public event EventHandler<ComputerEventArgs> Stopped;
    public event EventHandler<ComputerEventArgs> Reset;
    public event EventHandler<ComputerErrorEventArgs> Error;
}

Vielen Dank soviel für Ihre Antworten! Schließlich beginne ich zu verstehen, was los ist. Nur eine Sache; Es scheint, dass, wenn jedes Ereignis eine unterschiedliche Anzahl / Art der Argumente hätte, würde ich eine andere :: EventArgs Klasse erstellen müssen damit umgehen:

public void computerStarted(Computer computer);
public void computerStopped(Computer computer);
public void computerReset(Computer computer);
public void breakPointHit(Computer computer, int breakpoint);
public void computerError(Computer computer, Exception exception);

Dies würde drei classses erfordert mit den Ereignissen zu tun !? (Na ja zwei benutzerdefinierte, und man den Standard EventArgs.Empty-Klasse)

Cheers!

Ok, Nachklärung !: Also das ist so ziemlich das Beste, was ich Code weise tun können, um diese Ereignisse zu implementieren?

   public class Computer {

        public event EventHandler Started;

        public event EventHandler Stopped;

        public event EventHandler Reset;

        public event EventHandler<BreakPointEvent> BreakPointHit;

        public event EventHandler<ExceptionEvent> Error;

        public Computer() {
            Started = delegate { };
            Stopped = delegate { };
            Reset = delegate { };
            BreakPointHit = delegate { };
            Error = delegate { };
        }

        protected void OnStarted() {
            Started(this, EventArgs.Empty);
        }

        protected void OnStopped() {
            Stopped(this, EventArgs.Empty);
        }

        protected void OnReset() {
            Reset(this, EventArgs.Empty);
        }

        protected void OnBreakPointHit(int breakPoint) {
            BreakPointHit(this, new BreakPointEvent(breakPoint));
        }

        protected void OnError(System.Exception exception) {
            Error(this, new ExceptionEvent(exception));
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top