AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Multicast Events

Ein Thema von Stevie · begonnen am 22. Feb 2011 · letzter Beitrag vom 26. Aug 2021
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#1

Multicast Events

  Alt 22. Feb 2011, 19:53
Da es in .Net denkbar einfach ist, mehr als einen EventHandler an ein Event zu hängen, habe ich auf Basis des source codes von Allen Bauer ([1], [2], [3]) das ganze noch etwas ausgebaut um es möglichst einfach zu machen, Events zuzuweisen.
Leider fand ich in Bauers Beiträgen den vollständigen source code nirgens und musste einiges selbst rekonstruieren.

Es gibt mehrere Möglichkeiten, diese Events zu benutzen.
Angenommen, ich habe einen Button und möchte an das OnClick 2 EventHandler hängen:
Delphi-Quellcode:
var
  eventHandler: TEventHandler<TNotifyEvent>;
begin
  eventHandler := TEventHandler<TNotifyEvent>.Create(Button1);
  eventHandler.Add(ClickHandler1);
  eventHandler.Add(ClickHandler2);
  Button1.OnClick := eventHandler.Invoke;
end;
Dabei ist interessant, dass man beim Konstruktor einen Owner angeben kann. Dadurch muss man wie bei TComponent üblich nicht um das Freigeben des Objektes kümmern.

Wenn man eine eigene Klasse erstellt gibt es neben dem Erstellen eines TEventHandler<T> Objektes eine andere (und elegantere wie ich finde) Möglichkeit:
Delphi-Quellcode:
type
  TFoo = class
  private
    FOnClick: TEvent<TNotifyEvent>;
  public
    procedure Click;
    property OnClick: TEvent<TNotifyEvent> read FOnClick;
  end;

procedure TFoo.Click;
begin
  FOnClick.Invoke(Self);
end;

var
  foo: TFoo;
begin
  foo := TFoo.Create;
  foo.OnClick.Add(ClickHandler1);
  foo.OnClick.Add(ClickHandler2);
end;
Man muss sich hier nicht um das Erzeugen und Verwalten eines Objektes kümmern, sondern kann das Event fast genauso nutzen wie bei regulären Events, außer, dass die Eigenschaft nur read sein muss (und sollte).
Angehängte Dateien
Dateityp: pas System.Events.pas (8,3 KB, 133x aufgerufen)
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (23. Feb 2011 um 11:19 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.119 Beiträge
 
Delphi 12 Athens
 
#2

AW: Multicast Events

  Alt 23. Feb 2011, 06:58
Du könntest ja noch sowas mit ausfnehmen:
Delphi-Quellcode:
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1.OnClick);
eventHandler.Add(ClickHandler1);
eventHandler.Add(ClickHandler2);
Aus dem übergebenen TNotifyEvent kannst'e dir auch gleich das Objekt rausziehen und direkt als Owner nutzen.
Oder gib mir einfach ein paar Sekunden Zeit.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#3

AW: Multicast Events

  Alt 23. Feb 2011, 09:38
Du könntest ja noch sowas mit ausfnehmen:
Delphi-Quellcode:
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1.OnClick);
eventHandler.Add(ClickHandler1);
eventHandler.Add(ClickHandler2);
Aus dem übergebenen TNotifyEvent kannst'e dir auch gleich das Objekt rausziehen und direkt als Owner nutzen.
Oder gib mir einfach ein paar Sekunden Zeit.
Mir erschließt sich der Nutzen noch nicht. Der auf Button1.OnClick zugewiesene Eventhandler ist ja in der Regel eine ganz anderes Objekt. Warum sollte dieses der Owner für den Eventhandler für Button1 sein? Außerdem macht es imo keinen Sinn, wenn dieses Objekt die Livetime für den Eventhandler von Button1 regelt.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.119 Beiträge
 
Delphi 12 Athens
 
#4

AW: Multicast Events

  Alt 23. Feb 2011, 09:46
Man bekommt den Owner und die Methode zusammen übergeben?

Delphi-Quellcode:
constuctor TEventHandler<T>.Create(OwnerMethod: T; AddEvents: array of T);
begin
  inherited Create(TComponent(TMethod(OwnerMethod).Data)); // Owner
  for M in AddEvents do
    Add(M);
end;
statt
Delphi-Quellcode:
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1);
eventHandler.Add(ClickHandler1);
eventHandler.Add(ClickHandler2);
Button1.OnClick := eventHandler.Invoke;
einfach
Delphi-Quellcode:
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1.OnClick);
eventHandler.Add(ClickHandler1);
eventHandler.Add(ClickHandler2);
oder gar so
TEventHandler<TNotifyEvent>.Create(Button1.OnClick, [ClickHandler1, ClickHandler2]); .

In dem TMethod (Button1.OnClick) steckt ja schon alles drin > die aufzurufende Methode und das Objekt, welches man als Owner verwenden kann.

Ja, ich geb's zu ... ich bin ein schreibfauler Programmierer , aber ich steh dazu
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (23. Feb 2011 um 09:52 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Multicast Events

  Alt 23. Feb 2011, 10:16
Man bekommt den Owner und die Methode zusammen übergeben?

Delphi-Quellcode:
constuctor TEventHandler<T>.Create(OwnerMethod: T; AddEvents: array of T);
begin
  inherited Create(TComponent(TMethod(OwnerMethod).Data)); // Owner
  for M in AddEvents do
    Add(M);
end;
statt
Delphi-Quellcode:
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1);
eventHandler.Add(ClickHandler1);
eventHandler.Add(ClickHandler2);
Button1.OnClick := eventHandler.Invoke;
einfach
Delphi-Quellcode:
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1.OnClick);
eventHandler.Add(ClickHandler1);
eventHandler.Add(ClickHandler2);
oder gar so
TEventHandler<TNotifyEvent>.Create(Button1.OnClick, [ClickHandler1, ClickHandler2]); .

In dem TMethod (Button1.OnClick) steckt ja schon alles drin > die aufzurufende Methode und das Objekt, welches man als Owner verwenden kann.

Ja, ich geb's zu ... ich bin ein schreibfauler Programmierer , aber ich steh dazu
Mich würde es ehrlich gesagt sehr wundern, wenn das funktioniert...

Wenn ich so einen TEventHandler erzeuge, so möchte ich den doch einem Event zuweisen, welches bisher noch kein Event zugewiesen hat, also bei dem folgendes zutrifft:

Delphi-Quellcode:
TMethod(OnClick).Code = Nil
TMethod(OnClick).Data = Nil
Selbst wenn jedoch bereits ein Event an mein OnClick zugewiesen ist, enthält TMethod(OnClick).Data jedoch eine Referenz auf das Objekt, dem der Eventhandler gehört, nicht jedoch zu dem Objekt, welches die Eventeigenschaft hat...

Im Code:

Delphi-Quellcode:
Button1.OnClick := Form1.HandleOnClick;

Assert(TMethod(Button1.OnClick).Data = Button1); // schlägt fehl
Assert(TMethod(Button1.OnClick).Data = Form1); // erfolgreich
Wenn ich nicht die ganzen letzten Jahre das Konzept von TMethod missverstanden hab, dann kann deine Unterstützung der Schreibfaulheit nicht funktionieren.

Gruß,
Sven
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#6

AW: Multicast Events

  Alt 23. Feb 2011, 10:23
Der zweite Vorschlag mit dem Array an EventHandlern find ich gut.

Das andere funktioniert allerdings nicht, da du dazu eine Referenz auf die Property und nicht den Inhalt übergeben müsstest, und das geht in Delphi nunmal nicht (zumindest nicht auf diesem Wege)

P.S.:
Mit dem überladenen Konstruktor geht aber immerhin folgendes, was auch nicht viel kürzer ist, als das, was du erreichen wolltest:
Delphi-Quellcode:
Button1.OnClick := TEventHandler<TNotifyEvent>.Create(
  Button1, [ClickHandler1, ClickHandler2]).Invoke;
P.P.S: Das inherited in dem Konstruktor ist übrigens fehl am Platze.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (23. Feb 2011 um 11:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#7

AW: Multicast Events

  Alt 23. Feb 2011, 12:39
Was hälst du von der Idee:
Delphi-Quellcode:
// Zwei Listener hinzufügen, können auch beliebig viele sein
EventHandler.Add(Button1.OnClick, MethodA, MethodB);

// Weiteren Listener hinzufügen
EventHandler.Add(Button1.OnClick, MethodC);

// Einen Listener entfernen, können evtl. auch mehrere sein
EventHandler.Remove(Button1.OnClick, MethodA);

// Alle Listener entfernen
EventHandler.Remove(Button1.OnClick);
Eine Instanz des EventHandlers gibt es somit zur gesamten Laufzeit, welche dann die Aufrufe intern "verknüpft". Problem hierbei ist, dass der Compiler nicht prüfen kann, ob die Parameter von OnClick und MethodA übereinstimmen. Wobei ich mir das sehr bequem vorstellen kann, zumal es etwas weniger Schreibarbeit ist

-- EDIT

Mit den Generics kann man auch noch dem Compiler das Meckern beibringen:
Delphi-Quellcode:
procedure EventHandler.Add<T>(const Source: T; const Dest: T);
begin
end;

EventHandler.Add<TNotifyEvent>(Button1.OnClick, MethodA);
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)

Geändert von s.h.a.r.k (23. Feb 2011 um 12:42 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: Multicast Events

  Alt 23. Feb 2011, 16:32
Wenn man Properties (und darum handelt es sich bei Button1.OnClick) an eine Methode übergibt, dann geht das nur call by value und nicht call by reference (was du hier bräuchtest).
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
ToFaceTeKilla

Registriert seit: 17. Mai 2006
Ort: Leipzig
283 Beiträge
 
Delphi XE2 Professional
 
#9

AW: Multicast Events

  Alt 17. Jan 2013, 14:01
Hiho,

auch wenn der Thread schon wieder etwas älter ist, hab ich mal eine Frage dazu:

Ich benutze die von Stevie bereitgestellte Unit um in einer von TClientSocket abgeleiteten Komponente mehrere Eventhandler für OnDisconnect und OnError zu ermöglichen.
Hintergrund ist, dass ich möchte, dass die Komponente in diesen beiden Events automatisch reconnectet (ohne Fehlermeldung) und gleichzeitig noch andere Eventhandler darauf registriert werden können.
Dafür muss ich im OnError den ErrorCode, welcher ein var-Parameter ist, auf 0 setzen. Beim Schreiben tritt allerdings eine AV auf.

Nun die Frage: Woran könnte das liegen und lässt sich das irgendwie beheben?

Vielen Dank für die Aufmerksamkeit
Billy Gerwitz
"Bei der Softwareentwicklung suchen wir nicht den richtigen Weg, sondern den am wenigsten falschen." - frei nach V. Hillmann
  Mit Zitat antworten Zitat
BlueStarHH

Registriert seit: 28. Mär 2005
Ort: Hannover-Hainholz
801 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Multicast Events

  Alt 26. Aug 2021, 13:36
Hi,

gibt es in aktuellen Delphi-Versionen schon Multicast-Events oder muss man immer noch diese Unit nutzen?

Danke und Gruß
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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:23 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