![]() |
In Events anderer Komponenten einklinken - Kreuzreferenzen
Ich fange in einigen Komponenten gerne Ereignisse anderer Komponenten ein ('capture events') und speichere dabei einen Zeiger auf eine evt schon zugewiesene Ereignisroutine, damit diese nicht 'abgehängt' wird, sondern in der 'untergeschobenen' Routine ebenfalls mit aufgerufen werden kann. Das sieht in etwa so aus:
Delphi-Quellcode:
Und die Ereignisroutine selbst etwa so:
procedure TADOPosManager.UpdateLinks;
{inline compare:} function IsSameEvent(E1, E2: TDatasetNotifyEvent): boolean; type TEventPointer = record case Integer of 1: (E: TDatasetNotifyEvent); 2: (P: Pointer); end; var P1, P2: TEventPointer; begin P1.E := E1; P2.E := E2; Result := (P1.P = P2.P); end; begin if (FTable <> nil) then begin with FTable do begin if not IsSameEvent(OnNewRecord,DoOnNewRecord) then FOrgOnNewRecord := OnNewRecord; OnNewRecord := DoOnNewRecord; end; end else ...
Delphi-Quellcode:
Durch 'IsSameEvent' bei der Zuweisung kann ich sicherstellen, daß ich mir keine endlose Rekursion innerhalb ein und derselben Komponente einfange (mit dem unvermeidlichen 'stack overflow') - aber wie sieht das aus, wenn ich mehrere Komponenten mit derselben Technik einsetze und vermeiden will, daß die eine jeweils die 'untergeschobene' Routine der anderen als 'Original' betrachtet? Kann ich irgendwie feststellen, wem eine bereits zugewiesene Routine 'gehört' (also zB einem Form oder Frame - oder eben einer anderen Komponente)? Bei einem einfachen wechselseitigen Aufruf würde auch helfen, die Adresse (den Zeiger) der aufrufenden Routine mit der (dem) der aufzurufenden Routine zu vergleichen, aber das schützt schon nicht mehr vor einer drei- oder mehrfachen Rekursionschleife.
procedure TADOPosManager.DoOnNewRecord(ADataset: TDataset);
begin ADataset.FieldByName(FFieldName).AsInteger := FNewNr; if Assigned(FOrgOnNewRecord) then FOrgOnNewRecord(ADataSet); end; Oder hat jemand bessere Vorschläge? Oder ist die ganze Vorgehensweise einfach 'Mist' und Rekursionen lassen sich nicht zuverlässig vermeiden...? peinhard [edit=r_kerber]code- durch delphi-Tags ersetzt. Mfg, r_kerber[/edit] |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Moin moin Peinhard,
herzlich willkommen in der Delphi-PRAXiS. Einen Hinweis noch. Wir haben für Delphi eigene Formatierungs-Tags. Das nächste mal, benutze bitte diese, dann wird Delphi-Code noch schöner formatiert. |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Hallo Peinhard,
zwei Dinge möchte ich zu deiner Vorgehensweise anmerken. Zuerst, das hijacking von Events sollte nicht in einer beliebigen Methode erfolgen - der constructor oder eine spezielle Methode Attach() oder Tap() wären meine Wahl. Und nicht zuletzt, wenn du schon in Erwägung ziehst, dass mehrere Komponenten dasselbe Event derselben Komponente belauschen können sollen, dann reicht dein Ansatz mit dem Zwischenspeichern des alten event handlers vielleicht nicht aus - eine chain of event handlers (verkettete Liste?) wäre dann effektiver. Insbesondere, weil das Detach() bzw. Untap() dann in beliebiger Reihenfolge stattfinden kann. Freundliche Grüße vom marabu |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Moin marabu,
erstmal vielen Dank für die Antwort. Der constructor einer 'lauschenden' Komponente ist deshalb weniger geeignet, weil zu diesem Zeitpunkt andere über properties eingebundene Komponenten (die 'zu belauschenden') noch gar nicht verfügbar sind. Da wäre also Loaded die erste 'zentrale' Möglichkeit, aber wiederum auch nicht für zur Laufzeit zugewiesene Komponenten. Und dann lande ich wieder bei der Set-Methode des jeweiligen property. Das UpdateLinks aus meinem Code-Schnipsel wird auch aus einer solchen heraus aufgerufen - und ein weiterer Auruf in Loaded ('zur Sicherheit' sozusagen...) brachte mir den ersten Stackoverflow in einer meiner Anwendungen ein... Kannst du vielleicht auch noch mal etwas genauer darauf eingehen, was dur dir unter Attach() oder Tap() vorstellen würdest? Was wäre der zentrale Unterschied zu einer Methode wie eben des angeführten UpdateLinks? Und für eine verkettete Liste bräuchte man wohl eine Art 'Zentralinstanz', bei der sich sowohl die 'Lauscher' als auch die 'Belauschten' anzumelden hätten und die diese Liste dann eben 'zentral' verwalten könnte/müßte, sehe ich das richtig...? Gruß zurück, peinhard |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Hallo peinhard,
vergiss die verkettete Liste - Mehrfachbeziehungen zwischen Komponenten scheinen nicht dein Problem zu sein. Beim Laden deiner Komponente aus dem DFM-Stream (Loaded) erkennst du, dass zur Entwurfszeit eine Komponente an die property Table zugewiesen wurde, welche über einen event handler OnNewRecord() verfügt, der gleichfalls zur Entwurfszeit festgelegt wurde. Was machst du, wenn der event handler der externen DataSet-Komponente, auf welche FTable verweist, zur Laufzeit geändert wird - nachdem deine Komponente intern bereits eigenen Code vorgeschaltet hat? Damit will ich andeuten, dass man eine genauere Beschreibung der Funktionalität deiner Komponente braucht, um vernünftige und praktikable Vorschläge zur Implementierung machen zu können. Die Vorgabe eines surrogate key in deiner Vorschaltroutine ist wohl auch kein gutes Beispiel - diese Funktionalität wäre im eigentlichen event handler des DataSets wohl besser aufgehoben. Zitat:
Freundliche Grüße marabu |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Hello again...
Zitat:
Zitat:
Zitat:
Zitat:
Wieder Gruß zurück, peinhard |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Ich nochmal.
Zitat:
Zitat:
Zitat:
![]() Zur Abwechslung mal ohne Grüße marabu |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Zitat:
Zitat:
Zitat:
peinhard |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Zitat:
Zitat:
marabu |
Re: In Events anderer Komponenten einklinken - Kreuzreferenz
Ich wollt' nur sagen, daß das Thema für mich nicht gestorben ist - ich komm nur einfach im Moment nicht dazu, auch am WE nicht. Das 'observer pattern' ist mE deshalb nicht ganz zutreffend, weil ja das (beobachtete) 'Subjekt' die Schnittstelle(n), um die es geht (die Events) standardmäßig immer nur für einen Beobachter bereithalten - deshalb ja der Rückgriff auf die Verkettung, mit eben der Gefahr dabei wieder auf ein Glied bzw den Anfang der bereits existierenden Kette zurückzuspringen und eine Endlosschleife 'zu bauen'. Vielleicht fasse ich hier aber auch das Subjekt nicht richtig auf...?
Und auch wieder einen Gruß zur Nacht - jetzt wird erstmal auf Analogtechnik umgeschaltet ;) peinhard |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:47 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