Laden...

Generische Event-Klasse

Erstellt von Löwenherz vor 17 Jahren Letzter Beitrag vor 16 Jahren 3.579 Views
L
Löwenherz Themenstarter:in
58 Beiträge seit 2006
vor 17 Jahren
Generische Event-Klasse

Hallo Forum 🙂

Ich hätte mal wieder eine Frage an euch und hoffe, dass ihr vielleicht eine Lösung dafür auf Lager habt 🙂

Um es kurz zu machen:
Ich möchte mein Projekt mit Remoting aufziehen und stehe vor dem Problem, dass Remoting nur sehr rudimentäre Event-Unterstützung zu haben scheint. Das wesentliche Problem dürfte die sequentielle Abarbeitung von Aufrufen beim Feuern eines Events sein. Ich möchte die ganzen Aufrufe parallelisieren und jeden Aufruf von einem Threadpool durchführen lassen. Ich habe vor, eine generische Eventklasse zu bauen, die als Parameter den Delegaten übernimmt, der zur aufzurufenden Methode passt, so dass man ein Event einfach nur noch wie folgt erzeugen muss:

Event<MyEventHandler> m_event;

Mein Problem ist nun, wie kann ich das realisieren? 😉
Die bisherige Event-Klasse seht ihr unten. Mir fehlt vor allem folgendes:

  • die Einschränkung des Typs T auf Delegaten
  • und eine Methode Fire(), die als Argumente die Argumente des entsprechenden Delegaten hat

Das ist schon eine harte Nuss - zumindest weiß ich spontan nicht, wie ich das machen könnte bzw. ob das überhaupt geht, was ich vorhabe ^^


using System;
using System.Collections.Generic;
using System.Text;

namespace Test
{
  class Event<T>
  {
    private List<T> m_Listener;
    
    public void AttachListener(T listener)
    {
      m_Listener.Add(listener);
    }

    public void DetachListener(T listener)
    {
      m_Listener.Remove(listener);
    }
  }
}

Ich bedanke mich schon einmal im voraus bei euch 🙂

Viele Grüße,
Löwenherz

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ich fürchte, ich habe den Unterschied zwischen public event myEventType myEvent; und public Event<myEventType> myEvent; nicht ganz verstanden...

L
Löwenherz Themenstarter:in
58 Beiträge seit 2006
vor 17 Jahren

Die "normalen" Events unter .NET werden ja sequentiell nacheinander abgearbeitet, und genau das will ich nicht - Ich möchte, dass die Clients des Events asynchron abgearbeitet werden. Und zu allem Überfluss muss das Ding auch noch mit Remoting funktionieren, aber da kümmere ich mich danach drum. Jetzt muss erstmal das asynchrone Event an sich funktionieren.

Löwenherz

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Löwenherz,

die "normalen" Events unter .NET kannst du auch asynchron abarbeiten.

Statt


if (MyEvent != null) {
   MyEvent (this, e);
}

gehst du einfach mit foreach alle in MyEvent enthaltenen Delegaten durch und kann die dann einzeln so aufrufen, wie immer du willst.

herbivore

L
Löwenherz Themenstarter:in
58 Beiträge seit 2006
vor 17 Jahren

Hmmm, das werde ich mir morgen gleich als erstes mal anschauen 🙂

Wenn ich das mal rein theoretisch betrachte ... Dann müsste ich überall, wo ich ein Event asynchron abarbeiten will, ja diesen Aufwand mit foreach und BeginInvoke treiben 😉 Kann man das nicht etwas kapseln ? ^^

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Löwenherz,

ja, sollte sich leicht kapseln lassen.

herbivore

L
Löwenherz Themenstarter:in
58 Beiträge seit 2006
vor 17 Jahren

Hallo Herbivore,

das ist ganz bestimmt so, nur kann ich mir beim besten Willen nicht vorstellen, wie das gehen soll, da man keine Ableitungen von Delegate oder MulticastDelegate bilden und scheinbar auch nicht explizit auf diese Typen casten kann 😕

*verzweifelt*

Löwenherz

PS: Am liebsten wäre mir natürlich die Lösung mit der generischen Klassen, da man sich damit auch gleich Typsicherheit mit ins Haus holt - und ein Programmierer dann nichts mehr falsch machen kann 🙂

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Löwenherz,

ich habe das Beispiel aus Problem mit EventHandler auf die o.g. foreach-Lösung umgestellt, wobei das foreach in einer extra Methode gekapselt ist, die man auch in eine allgemeine Hilfsklasse auslagern könnte. Die Methode heitß SyncInvokeEvent und ich denke es sollte ein leichtes für dich sein, daraus ein AsyncInvokeEvent zu konstruieren.

Typsicher ist das Beispiel nicht, aber es funktioniert für beliebige EventHandler-Typen. Vielleicht kann man das Ganze auch noch typsicher machen, habe ich noch nicht überlegt.


using System;

public class Test
{
   public event EventHandler MyEvent;

   protected void OnMyEvent (EventArgs ea)
   {
      SyncInvokeEvent (MyEvent, this, ea);
   }

   public void SyncInvokeEvent (MulticastDelegate md, params Object [] ao)
   {
      foreach (Delegate d in md.GetInvocationList ()) {
         // Die Methode könnte man natürlich auch in einem Thread oder auf
         // andere Art Asynchron starten
         d.DynamicInvoke (ao);
      }
   }

   public void DoSomething ()
   {
      // ...
      OnMyEvent (EventArgs.Empty);
      // ...
   }

}

abstract class App
{
   public static void Main (string [] astrArg)
   {
      Test test = new Test ();

      test.MyEvent += new EventHandler (ThisMyEvent);
      test.DoSomething ();
   }

   public static void ThisMyEvent (Object objSender, EventArgs ea)
   {
      Console.WriteLine ("ThisMyEvent (" + objSender + ", "
                                         + ea + ")");
   }
}

herbivore

I
1 Beiträge seit 2007
vor 16 Jahren

Hallo Löwenherz,

ich weiß nicht, ob Du inzwischen das Problem lösen konntest - ich bin eher durch Zufall auf diesen Thread gestossen.

Nun, ich denke dass Dein Ansatz - der Versuch einen eigenen generischen Event zu schreiben - um Ihn zum einen asynchron und zum zweiten remotefähig zu machen etwas zu seher um die komplizierte Ecke gedacht ist.

Das asynchrone abfeuern von Events ist relativ einfach zu lösen, zumal jedes Delegate auch einen asynchronen Aufruf unterstützt (Methoden BeginInvoke / EndInvoke).

Bei den Remoting-Fähigkeiten von Events hat man immer das klassische "Referenzierungsproblem", zumal ein delegate auf eine bekannte Methode zeigen muss, damit er ausgeführt werden kann. Man kann sich da relativ gut aushelfen, in dem man eine "Shared Assembly" aufzieht, die von Client- und Server-Kompontente referenziert wird. Beide verwenden dann zwei "Überbrückungs-Klassen" um den Event auf die Gegenseite zu schaufeln.

Ich habe erst vor kurzem mich mit dem Thema wieder auseinandergesetzt und einen kleinen Erfahrungsbericht mit Code-Beispiel geschrieben:

Remote Events mit .NET 2.0

Ich denke, dass könnte bei Deinem Problem einen weiteren Schritt zur Lösung sein.

Viel Erfolg,
icx