AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Auf Interface basierende MultiCastEvents
Thema durchsuchen
Ansicht
Themen-Optionen

Auf Interface basierende MultiCastEvents

Ein Thema von geskill · begonnen am 27. Dez 2012
Antwort Antwort
Benutzerbild von geskill
geskill

Registriert seit: 17. Feb 2007
Ort: NRW
420 Beiträge
 
Delphi 2010 Professional
 
#1

Auf Interface basierende MultiCastEvents

  Alt 27. Dez 2012, 17:46
.
Warum MultiEvents?
Die nativen Events in Delphi haben zwei große Nachteile:
  1. Es ist eine 1 zu 1 Verbindung, es gibt ein Event-Auslöser (trigger) und den Event-Zuhörer (event listener or handler)
    jedoch ist es oftmals gewünscht an mehreren Stellen auf ein Event zu reagieren.
    Die MultiEvents führen hier die aus vielen anderen Programmiersprachen (z.B. Java) bekannte 1 zu N Verbingdung ein,
    in der sich zu einem Event X mehrere Zuhörer über die Add() Methode registrieren können.
  2. Die Events sind nur innerhalb des Delphi Sprachraums gültig. Für programmiersprachenübergreifende Schnittstellen gibt
    es keine "out of the box" Lösung.
    Das besondere an den MultiEvents ist die programmiersprachenübergreifende Verträglichkeit. Durch Interfaces und COM
    Datentypen ermöglichen dies den Einsatz in großen Plug-In Systemen.

Außerdem nutzen die MultiEvents geschickt die in D2009+ eingeführten Generics
um den Mehraufwand an Code auf ein Minimum zu reduzieren.
Inhalt
  1. Interfaces als Ausgangspunkt
    • 1 zu 1 Verbindung
    • 1 zu N Verbindung
  2. Einfache Benutzung
    • Event-Auslöser Betrachtung
    • Event-Zuhörer Betrachtung
  3. Quellcodeminimierung durch Generics
    • TGenericEventHandler Klasse
    • TGenericEvent Klasse
  4. Verweise
    • Ähnliche Ansätze

1. Interfaces als Ausgangspunkt
1 zu 1 Verbindung
Ganz ohne das alt bekannte procedure ... of object Gerüst geht es nicht. Zusätzlich wird ein EventHandler Interface definiert.
Delphi-Quellcode:
  TNotifyMethod = procedure(const Sender: IUnknown) of object;

  INotifyEventHandler = interface(IUnknown)
    ['{EE9407DD-2337-4DFC-BC35-A40C4FA0A1A7}']
    procedure Invoke(const Sender: IUnknown); safecall;
  end;
Aus diesen beiden "Bauteilen" entsteht die TINotifyEventHandler Klasse, die das zuvor definierte Interface implementiert. Dies ist eine Art Wrapper für die TNotifyMethod.
Delphi-Quellcode:
  TINotifyEventHandler = class(TGenericEventHandler<TNotifyMethod>, INotifyEventHandler)
  public
    procedure Invoke(const Sender: IUnknown); safecall;
  end;
1 zu N Verbindung
Hat man erstmal einen EventHandler definiert kann man daraus nun ein entsprechendes MultiEvent erstellen. Über Add, Remove können dann Instanzen des INotifyEventHandlers hinzugefügt und wieder entfernt werden. Mit Invoke ruft man das Event auf. Somit werden alle Events die in dem MultiEvent registriert sind benachrichtigt.
Delphi-Quellcode:
  INotifyEvent = interface(IUnknown)
    ['{14551B63-78C4-4A70-9E54-7656CEF4D6A7}']
    procedure Add(const AHandler: INotifyEventHandler); safecall;
    procedure Remove(const AHandler: INotifyEventHandler); safecall;
    procedure Invoke(const Sender: IUnknown); safecall;
  end;
Für die Implementierung reicht es eine for-Schleife in der Invoke-Methode zu tippen:
Delphi-Quellcode:
  TINotifyEvent = class(TGenericEvent<INotifyEventHandler>, INotifyEvent)
  public
    procedure Invoke(const Sender: IUnknown); safecall;
  end;

2. Einfache Benutzung
Event-Auslöser Betrachtung
In der Klasse in der ein MultiEvent eingesetzt werden soll wird eine lokale Variable FNotifyEvent: INotifyEvent; definiert. Außerdem muss für den Zugriff von außen gesorgt werden - am Besten durch eine property und einen getter.

Die Erstellung, ein Aufruf und die Zerstörung ist so einfach wie es nur sein kann:
Delphi-Quellcode:
// Im constructor der Klasse
FNotifyEvent := TINotifyEvent.Create;

// button1 von Typ TButton
// Eine Event Nachricht/Aufruf sieht das bspw. so aus
NotifyEvent.Invoke(button1);

// Im destructor der Klasse
FNotifyEvent := nil;

Event-Zuhörer Betrachtung
Die Klasse die sich beim MultiEvent registiert. Wie schon erwähnt benötigt diese Zugriff auf das MultiEvent (hier: Main.NotifyEvent).
Delphi-Quellcode:
  TOtherForm = class(TForm)
    // [...]
  private
    FNotifyEventHandler: INotifyEventHandler;
  protected
    // Diese Methode wird dann aufgerufen
    procedure OnNotify(const Sender: IUnknown);

// [...]

// Im constructor der Klasse
  FNotifyEventHandler := TINotifyEventHandler.Create(OnNotify);
  Main.NotifyEvent.Add(FNotifyEventHandler);

// Im destructor der Klasse
  Main.NotifyEvent.Remove(FNotifyEventHandler);
  FNotifyEventHandler := nil;


3. Quellcodeminimierung durch Generics
TGenericEventHandler Klasse
Delphi-Quellcode:
  TGenericEventHandler<T: constructor> = class abstract(TInterfacedObject)
  protected
    FHandler: T;
  public
    constructor Create(AEventHandler: T);
    property EventHandler: T read FHandler write FHandler;
    destructor Destroy; override;
  end;
TGenericEvent Klasse
Delphi-Quellcode:
  TGenericEvent<T: IUnknown> = class abstract(TInterfacedObject)
  private
    FMethods: TList<T>;
  protected
    property Methods: TList<T>read FMethods;
  public
    constructor Create; virtual;
    procedure Add(const AHandler: T); safecall;
    procedure Remove(const AHandler: T); safecall;
    destructor Destroy; override;
  end;


4. Verweise
Die Arbeit von Jolyon Smith hat mich ich für MultiEvents auf Interface-Basis inspiriert. Da dies mMn noch nicht Dokumentiert ist, sollte es an dieser Stelle ganz gut aufgehoben sein.

Ähnliche Ansätze
http://www.delphipraxis.net/158578-m...st-events.html
Multicast events using generics


Im Anhang befindet sich der komplette Quellcode und ein kleines Beispiel. Die Events lassen sich natürlich nach eigenen Wünschen beliebig anpassen und unter Verwendung der generischen Klassen, sollte sich die Tipparbeit in Grenzen halten.

Viel Spaß damit.
.
Angehängte Dateien
Dateityp: zip MultiEvents.zip (10,1 KB, 26x aufgerufen)
Sebastian

Geändert von geskill (25. Feb 2013 um 22:56 Uhr) Grund: Komplette Überarbeitung
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:21 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz