Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi CallBack lässt Object vergessen (https://www.delphipraxis.net/80610-callback-laesst-object-vergessen.html)

berens 12. Nov 2006 10:24


CallBack lässt Object vergessen
 
Hallo!

Ich habe ein Object, das von mehreren Objecten geändert werden kann. Es speichert zentral Informationen ab. Wenn die Informationen von einem Object geändert wurden, sollen diese Änderungen auch an die anderen Objekte weitergegeben werden. Dazu wird von den Objekten eine Callback-Funktion aufgerufen, und die Objekte (z.b. Object A) laden sich die Informationen von dem Daten-Object (Object B) neu.

Was muss ich anders machen?

Vielen Dank für baldige Antworten!


Bei allen Objecten A wurde das FObjectB (über eine Property) nach dem Erstellen zugewiesen.

Folgender Code bei Object A:
Delphi-Quellcode:
FObjectB: TObjectB;
FChangeCausedbyObjectB: Procedure of Object;
FChangeCausedbyObjectB:= ChangeCausedbyObjectB; // wird bei .Create zugewiesen
property ObjectB: TObjectB read FObjectB write SetObjectB;

procedure ObjectA.SetFObjectB(_ObjectB: TObjectB);
begin
  // Das ObjectB wird zugewiesen
  FObjectB:= _ObjectB;                                  
  // Ich kann nun gültige Informationen aus Object B auslesen. Soweit alles OK.
  // Die Funktion ObjectA.ChangeCausedbyObjectB auslösen lassen, wenn sich bei ObjectB etwas ändert.
  FObjectB.CallBackList.Add(@FChangeCausedbyObjectB);
end;

procedure ObjectA.ChangeCausedbyObjectB;
begin
  // Hier tritt nun das Problem auf, wenn diese Prozedur von ObjectB aufgerufen wird
  if assigned(FObjectB) then begin // FObjectB ist zugewiesen
    if FObjectB.InheritsFrom(TFObjectB) then begin // trifft nicht zu oder löst sogar Exception aus <-- PROBLEM
      FdtpAusblendDatum.DateTime := floor(FObjectB.User_EndDate);
    end;
  end;
end;
Folgender Code bei Object B:
Delphi-Quellcode:
CallBackList: TList; // wurde bei .Create miterschaffen

procedure ObjectB.Irgendwas;
var
  i: integer;
  CBProc: Procedure of Object;
begin
  for i := 0 to CallBackList.Count - 1 do begin // alle ObjekteA benachrichtigen
    if assigned(CallBackList.Items[i]) then begin
      try
        @CBProc := CallBackList.Items[i]; // Pointer auslesen
        CBProc; // d.h. alle Prozeduren aufrufen
      except
        on e: exception do begin
        end;
      end;
    end;
  end;
end;

berens 12. Nov 2006 12:36

Re: CallBack lässt Object vergessen
 
Also das Grundproblem liegt wohl darin jedes Mal, wenn diese Prozedur (procedure ObjectA.ChangeCausedbyObjectB;) aufgerufen wird, Self etwas (zufälliges) anderes ist. Im Moment ist es gerade ein TAdoQuery. Frag mich mal einer warum (klar, ich verwende die schon wo anders im Programm, aber wie kommt er darauf diese Prozedur als TAdoQuery auszuführen?).

Wie bekomme ich das Programm nun dazu, die Prozudur als _ursprüngliches Objekt_ aufzurufen, und -nicht- einfach nur als Prozedur...?

Der_Unwissende 12. Nov 2006 12:57

Re: CallBack lässt Object vergessen
 
Hi,

Was diese Stelle angeht:
Zitat:

Zitat von berens
Delphi-Quellcode:
    ....
    if FObjectB.InheritsFrom(TFObjectB) then begin // trifft nicht zu oder löst sogar Exception aus <-- PROBLEM

So solltest du schauen, was du in der Hilfe zum Thema inheritsFrom findest, dass ist eine Klassen-Methode, die nicht mit einer Referenz sondern mit einer Klasse aufgerufen wird. Du würdest also etwas Testen wie:
Delphi-Quellcode:
if TClassA.inheritsFrom(TClassB) then
...
Du rufst es also nicht mit für eine Instanz, sondern für eine Klasse auf und prüfst ob diese Klasse von einer anderen abgeleitet ist oder nicht.
Für eine Instanz wird der is-Operator verwendet:
Delphi-Quellcode:
var instance : TClassA;
begin
  instance := TClassA.Create;

  if instance is TClassB then
  ...
Das könnte schon dein Hauptfehler sein,
Gruß Der Unwissende

berens 12. Nov 2006 13:04

Re: CallBack lässt Object vergessen
 
Ich glaube, ich konnte das Problem lösen. Wie unter http://www.swissdelphicenter.ch/de/showcode.php?id=1671 nachzulesen ist,

Zitat:

// Methodenzeiger in Funktionszeiger umwandeln

// Oft ist es nötig, einer API-Funktion einen Funktionszeiger, der auf eine Callbackfunktion zeigt, zu
// übergeben. Leider ist ein Funktionszeiger mit Methodenzeigern inkompatibel, und so ist es zunächst
// unmöglich, eine Methode als Callback anzugeben.
// Man kann zwar einen Methodenzeiger auf die Art "@TKlasse.EineMethode" in einen Funktionszeiger casten,
// allerdings darf man dann in dieser Methode dann auf keine Variablen (und auch auf Methoden, die diese
// Variablen benutzen) der Klasse zugreifen, da diese immer Instanzgebunden sind und man in diesem Falle
// keine Instanz angegeben hat (ähnlich einer Klassenmethode).
Darf ich keine Prozedur verwenden, sondern nur eine Funktion. Absolute unsinnig von Delphi, aber "wenn's schä' macht"...

Änderungen:
FChangeCausedbyObjectB entfällt.

FObjectB.CallBackList.Add(Pointer(ChangeCausedbyOb jectB));

function TObjectA.ChangeCausedbyObjectB: Boolean;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:00 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-2025 by Thomas Breitkreuz