![]() |
Multicast Events
Liste der Anhänge anzeigen (Anzahl: 1)
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 (
![]() ![]() ![]() 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:
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.
var
eventHandler: TEventHandler<TNotifyEvent>; begin eventHandler := TEventHandler<TNotifyEvent>.Create(Button1); eventHandler.Add(ClickHandler1); eventHandler.Add(ClickHandler2); Button1.OnClick := eventHandler.Invoke; end; 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:
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).
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; |
AW: Multicast Events
Du könntest ja noch sowas mit ausfnehmen:
Delphi-Quellcode:
Aus dem übergebenen TNotifyEvent kannst'e dir auch gleich das Objekt rausziehen und direkt als Owner nutzen.
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1.OnClick);
eventHandler.Add(ClickHandler1); eventHandler.Add(ClickHandler2); Oder gib mir einfach ein paar Sekunden Zeit. |
AW: Multicast Events
Zitat:
|
AW: Multicast Events
Man bekommt den Owner und die Methode zusammen übergeben?
Delphi-Quellcode:
statt
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;
Delphi-Quellcode:
einfach
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1);
eventHandler.Add(ClickHandler1); eventHandler.Add(ClickHandler2); Button1.OnClick := eventHandler.Invoke;
Delphi-Quellcode:
oder gar so
eventHandler := TEventHandler<TNotifyEvent>.Create(Button1.OnClick);
eventHandler.Add(ClickHandler1); eventHandler.Add(ClickHandler2);
Delphi-Quellcode:
.
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 :oops:, aber ich steh dazu |
AW: Multicast Events
Zitat:
Wenn ich so einen
Delphi-Quellcode:
erzeuge, so möchte ich den doch einem Event zuweisen, welches bisher noch kein Event zugewiesen hat, also bei dem folgendes zutrifft:
TEventHandler
Delphi-Quellcode:
Selbst wenn jedoch bereits ein Event an mein
TMethod(OnClick).Code = Nil
TMethod(OnClick).Data = Nil
Delphi-Quellcode:
zugewiesen ist, enthält
OnClick
Delphi-Quellcode:
jedoch eine Referenz auf das Objekt, dem der Eventhandler gehört, nicht jedoch zu dem Objekt, welches die Eventeigenschaft hat...
TMethod(OnClick).Data
Im Code:
Delphi-Quellcode:
Wenn ich nicht die ganzen letzten Jahre das Konzept von
Button1.OnClick := Form1.HandleOnClick;
Assert(TMethod(Button1.OnClick).Data = Button1); // schlägt fehl Assert(TMethod(Button1.OnClick).Data = Form1); // erfolgreich
Delphi-Quellcode:
missverstanden hab, dann kann deine Unterstützung der Schreibfaulheit nicht funktionieren.
TMethod
Gruß, Sven |
AW: Multicast Events
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:
P.P.S: Das inherited in dem Konstruktor ist übrigens fehl am Platze.
Button1.OnClick := TEventHandler<TNotifyEvent>.Create(
Button1, [ClickHandler1, ClickHandler2]).Invoke; |
AW: Multicast Events
Was hälst du von der Idee:
Delphi-Quellcode:
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 :mrgreen:
// 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); -- 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); |
AW: Multicast Events
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).
|
AW: Multicast Events
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 |
AW: Multicast Events
Hi,
gibt es in aktuellen Delphi-Versionen schon Multicast-Events oder muss man immer noch diese Unit nutzen? Danke und Gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz