AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi In Events anderer Komponenten einklinken - Kreuzreferenzen
Thema durchsuchen
Ansicht
Themen-Optionen

In Events anderer Komponenten einklinken - Kreuzreferenzen

Ein Thema von Peinhard · begonnen am 8. Jul 2006 · letzter Beitrag vom 15. Jul 2006
Antwort Antwort
Peinhard

Registriert seit: 8. Jul 2006
152 Beiträge
 
#1

In Events anderer Komponenten einklinken - Kreuzreferenzen

  Alt 8. Jul 2006, 09:53
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:
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 ...
Und die Ereignisroutine selbst etwa so:

Delphi-Quellcode:
procedure TADOPosManager.DoOnNewRecord(ADataset: TDataset);
begin
  ADataset.FieldByName(FFieldName).AsInteger := FNewNr;
  if Assigned(FOrgOnNewRecord) then
    FOrgOnNewRecord(ADataSet);
end;
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.

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]
  Mit Zitat antworten Zitat
Benutzerbild von r_kerber
r_kerber

Registriert seit: 11. Feb 2003
Ort: Trittau
3.538 Beiträge
 
Delphi XE Professional
 
#2

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 8. Jul 2006, 10:27
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.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#3

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 11:13
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
  Mit Zitat antworten Zitat
Peinhard

Registriert seit: 8. Jul 2006
152 Beiträge
 
#4

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 11:52
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
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#5

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 15:30
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 von Peinhard:
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...?
Wenn du mit einer Zentralinstanz eine zusätzliche aktive Komponente meinst, dann nein. Du kannst die benötigte Observer-Funktionalität ja einfach in den event handler OnNewRecord() des DataSets packen und die Liste der Observer in einer ObjectList verwalten, welche du in DataSet.Tag mitführst.

Freundliche Grüße

marabu
  Mit Zitat antworten Zitat
Peinhard

Registriert seit: 8. Jul 2006
152 Beiträge
 
#6

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 16:30
Hello again...

Zitat von marabu:
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?
Blöd ausschauen, da die 'Observer-Komponente' immer noch unbekümmert den alten Handler aufrufen würde... es sei denn, ich rufe die Methode UpdateLinks des Observers auf, wenn ich den Handler 'umhänge' oder entferne...

Zitat von marabu:
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.
Ich glaube aber, daß die eigentliche Funktionalität der jeweiligen Komponenten nicht wirklich weiter hilft - dafür sind es auch einfach zu viele in ihrer Funktion völlig verschiedene, die sich inzwischen dieser 'Technik' (die noch nicht wirklich eine ist...) bedienen. Geh bitte wenn möglich einfach davon aus, daß zB jeder Dataset mehrere 'Observer' sowie evt zusätzliche event handler auf Form-Ebene haben kann (bzw haben können sollte).

Zitat von marabu:
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.
Hier steh ich auf'm Schlauch... was meinst du hier mit einem 'surrogate key'?

Zitat von marabu:
Wenn du mit einer Zentralinstanz eine zusätzliche aktive Komponente meinst, dann nein. Du kannst die benötigte Observer-Funktionalität ja einfach in den event handler OnNewRecord() des DataSets packen und die Liste der Observer in einer ObjectList verwalten, welche du in DataSet.Tag mitführst.
Das klingelt mir schon etwas einleuchtender, aber auch noch nicht wirklich 'plastisch'. Soweit ich das verstehe, müßte dann aber jeder Dataset der 'observiert' werden könnte, auch einen event handler auf Form-Ebene haben, der die 'Observer' koordiniert - und da würde ich dann doch schon wieder mit einer zentralen Instanz liebäugeln. Oder hättest du da vielleicht mal ein wenig Pseudo-Code, der mich noch weitergehender erhellt...?

Wieder Gruß zurück,

peinhard
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#7

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 19:11
Ich nochmal.

Zitat von Peinhard:
was meinst du hier mit einem 'surrogate key'?
Als surrogate key bezeichnet man in der angelsächsischen Literatur einen informationsfreien, weil künstlichen Schlüssel. Oft wird eine fortlaufende Zahl als surrogate key verwendet - auch wenn ein solcher Schlüssel streng genommen nicht vollständig informationsfrei ist.

Zitat von Peinhard:
Soweit ich das verstehe, müßte dann aber jeder Dataset der 'observiert' werden könnte, auch einen event handler auf Form-Ebene haben, der die 'Observer' koordiniert
Recht hast du.

Zitat von Peinhard:
und da würde ich dann doch schon wieder mit einer zentralen Instanz liebäugeln.
Das wäre dann aber schon ein observer manager. Dein Problem hierbei ist, dass du Komponenten eines FrameWorks einbinden willst, die das observer pattern nicht mitbringen. Mir scheint die Kosten-Nutzen-Ratio nicht gut genug zu sein, aber ich kann deine Motivation halbwegs nachvollziehen. Wenn du dich daran versuchen möchtest, dann helfen dir vielleicht ein paar Zeilen Code: Komponentenbeziehung herstellen

Zur Abwechslung mal ohne Grüße

marabu
  Mit Zitat antworten Zitat
Peinhard

Registriert seit: 8. Jul 2006
152 Beiträge
 
#8

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 19:36
Zitat von marabu:
Zitat von Peinhard:
was meinst du hier mit einem 'surrogate key'?
Als surrogate key bezeichnet man in der abgelsächsischen Literatur einen informationsfreien, weil künstlichen Schlüssel. Oft wird eine fortlaufende Zahl als surrogate key verwendet - auch wenn ein solcher Schlüssel streng genommen nicht vollständig informationsfrei ist.
Grmpf. Ich hätte besser fragen sollen, nämlich: 'Was willst du hier mit einem solchen, wie ihn einsetzen?'

Zitat von marabu:
Zitat von Peinhard:
und da würde ich dann doch schon wieder mit einer zentralen Instanz liebäugeln.
Das wäre dann aber schon ein observer manager. Dein Problem hierbei ist, dass du Komponenten eines FrameWorks einbinden willst, die das observer pattern nicht mitbringen. Mir scheint die Kosten-Nutzen-Ratio nicht gut genug zu sein, aber ich kann deine Motivation halbwegs nachvollziehen. Wenn du dich daran versuchen möchtest, dann helfen dir vielleicht ein paar Zeilen Code: Komponentenbeziehung herstellen
Wie gesagt, hat diese 'Technik' bei mir schon ziemlich um sich gegriffen, so daß die Aussicht auf eine weitgehend 'wartungsfreie' oder zumindest wartungsarme Implementation durchaus verlockend ist. Zumal ich mit einer abgeleiteten TADOConnection zumindest für Datasets schon eine quasi 'natürliche' Zentralinstanz dafür habe. Vielen Dank für den Code, den ich mir gleich mal ansehen und ihn dann 'überschlafen' werde...

Zitat von marabu:
Zur Abwechslung mal ohne Grüße
Dann eben ohne,

peinhard
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#9

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 10. Jul 2006, 19:59
Zitat von Peinhard:
Was willst du hier mit einem solchen, wie ihn einsetzen?
Wieso ich? Ich dachte du! Dein Code (...AsInteger := FNewNr) hatte mir suggeriert, dass du im Ereignis OnNewRecord() einen candidate oder gar primary key setzen wolltest. Wenn nicht, dann Schwamm drüber.

Zitat von Peinhard:
Dann eben ohne
Und jetzt wieder mit - Gute Nacht

marabu
  Mit Zitat antworten Zitat
Peinhard

Registriert seit: 8. Jul 2006
152 Beiträge
 
#10

Re: In Events anderer Komponenten einklinken - Kreuzreferenz

  Alt 15. Jul 2006, 21:41
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
  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 20:08 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