Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert es? (https://www.delphipraxis.net/161453-wie-kommt-ein-tdbedit-die-instanz-meines-datamodules-warum-wie-funktioniert-es.html)

RSE 4. Jul 2011 14:39

Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert es?
 
Hallo,

Standardfall:
In einer Unit MyDataModule ist die Klasse TMyDM = class(TDataModule) definiert. In dieser Klasse gibt es die DataSource MyDS. Zusätzlich gibt es in dieser Unit eine globale Variable MyDM: TMyDM. Nun kann in einer anderen Unit im Formdesigner in dem TDBEdit im Feld DataSource eingetragen werden "MyDM.MyDS".
Zur Laufzeit kann nun das DBEdit auf die Instanz der MyDS zugreifen. Ich habe mir nie den Kopf zerbrochen, wie das funktioniert - wird wohl irgendwie über die globale Variable funktionieren.

Komplizierterer Fall:
MyDs ist in TMyCustomDM definiert. Es gibt keine globale Variable MyCustomDM: TMyCustomDM. TMyCustomDM ist durch Visual Inheritance zu TMyDM abgeleitet und erbt damit MyDS. Es gibt auch keine globale Variable MyDM: TMyDM.
Nun gibt es eine Superklasse TMyCustomForm, auf der ein MyDBEdit: TDBEdit liegt. In TMyCustomForm gibt es eine public Eigenschaft DM: TMyCustomDM read FMyDM. TMyCustomForm ist durch Visual Inheritance zu TMyForm abgeleitet. In TMyForm wir die Eigenschaft DM verdeckt durch eine gleichnamige Eigenschaft DM: TMyDM read GetMyDM, wobei MyDM lediglich eine Typumwandlung durchführt: Result := TMyDM(FMyDM); Im Konstruktor von TMyForm wird das Datenmodul erzeugt: FMyDM := TMyDM.Create(Self); Die Instanz vom Typ TMyDM steckt also in TMyCustomForm.MyDM.
Nun kann ich im FormDesigner in TMyCustomForm.MyDBEdit in der Eigenschaft DataSource "MyCustomDM.MyDS" eintragen.
Auch in diesem Fall funktioniert MyDBEdit wie es soll. Ich kann mir nun aber beim besten Willen nicht mehr vorstellen, wie MyDBEdit an die Instanz des Datenmoduls kommt.

Zur Übersicht Auszüge aus den Units des komplizierteren Falls:
Delphi-Quellcode:
Unit UMyCustomDataModule;
type
  TMyCustomDM = class(TDataModule)
    MyDS: TDataSource;
  end;
Delphi-Quellcode:
Unit UMyDataModule;
type
  TMyDM = class(TMyCustomDM)
  end;
Delphi-Quellcode:
Unit UMyCustomForm;
type
  TMyCustomForm = class(TForm)
    MyDBEdit: TDBEdit;
  protected
    FMyDM: TMyCustomDM;
  public
    property MyDM: TMyCustomDM read FMyDM;
  end;
Delphi-Quellcode:
Unit UMyForm;
type
  TMyForm = class(TMyCustomForm)
  private
    function GetMyDM: TMyDM;
  public
    constructor Create(AOwner: TComponent); override;
    property MyDM: TMyDM read GetMyDM;
  end;
implementation

constructor TMyForm.Create(AOwner: TComponent);
begin
  FMyDM := TMyDM.Create(Self);
  inherited;
end;

function TMyForm.GetMyDM: TMyDM;
begin
  Result := TMyDM(FMyDM);
end;

RSE 5. Jul 2011 10:25

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zum Hintergrund der Frage: Ich möchte wissen, ob das nur zufällig funktioniert und vielleicht irgendwann nicht mehr geht oder gar Zugriffsverletzungen verursacht.

Ich habe zu dem Thema im Vorfeld versucht zu suchen, es ist mir aber nicht gelungen Suchwörter zu finden, die zu einer Erklärung dieses Sachverhaltes führten. Sollte der oben beschriebene Sachverhalt schon anderweitig beschrieben sein, dann bitte ich um einen kurzen Wegweiser dorthin.

schlecki 5. Jul 2011 10:29

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zitat:

Zitat von RSE (Beitrag 1109910)
Delphi-Quellcode:
Unit UMyCustomDataModule;
type
  TMyCustomDM = class(TDataModule)
    MyDS: TDataSource;
  end;

Keine Angabe der Sichtbarkeit wird mit
Delphi-Quellcode:
public
gleichgesetzt. Das sollte also immer funktionieren.

DeddyH 5. Jul 2011 10:30

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
War es nicht sogar published? Ich meine, in einer Fehlermeldung stand mal sowas.

schlecki 5. Jul 2011 10:31

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
hm, da ich nicht soo viel visuell arbeite, ist mir das eigentlich gleich :)

RSE 5. Jul 2011 13:09

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Keine Sichtbarkeitsangabe = published, ist für alle visuell erzeugten Komponenten Standard. Wer Zugriff auf eine Instanz der Klasse TMyDM hat, der hat auch Zugriff auf MyDS. So weit, so klar. Die Frage ist: Woher kennt die Komponente MyDBEdit die Adresse meiner Instanz von TMyDM? Diese Steckt ja in der Eigenschaft MyDM des Parents (Instanz der Klasse TMyForm) von MyDBEdit, aber das sage ich dem DBEdit ja zur Designtime nicht... MyDBEdit kennt nur "MyCustomDM.MyDS" - kein Hinweis auf Parent.MyDM.MyDS

stahli 5. Jul 2011 13:36

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Ich habe mal versucht zu folgen...
Evtl. gehst Du von etwas falschen Voraussetzungen aus (wenn das jetzt nicht auf mich selbst zutrifft :wink:).

Zur Designtime muss nicht die DBEdit die anzubindendenden Komponenten kennen bzw. finden, sondern ein Eigenschaftseditor, der auf die im Projekt eingebundenen Units direkt zugreift. Also muss die IDE die vorhandenen DataModule kennen, nicht die DBEdit. Die wartet nur stumpf, ob Ihr irgend etwas (von der IDE) zugewiesen wird.

RSE 5. Jul 2011 13:59

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zur Laufzeit muss das DBEdit ja wissen, woher es seine Anzeige lesen und wohin es seinen geänderten Text schreiben soll, dazu kann ich zur Designtime die Eigenschaften "DataSource" und "DataField" angeben. Diese werden dann zur Laufzeit benutzt, um auf die Datasource zuzugreifen und das Feld aus "DataField" zu lesen bzw. zu schreiben. D.h. aufgrund des Wertes in "DataSource" muss es zur Laufzeit möglich sein, die Instanz der Datasource zu finden. Die Property "DataSource" ist vom Typ TDatasource (also ein "Pointer" auf die Instanz einer Datasource). Da es zur Designtime schlecht möglich ist einen Pointer auf die Adresse zu hinterlegen, in der zur Laufzeit einmal das Objekt stehen wird, wird zur Designtime lediglich der Text "MyCustomDM.MyDS" hinterlegt, welcher dann beim Laden der Komponente MyDBEdit zur Laufzeit in einen Zeiger verwandelt werden muss. Die Frage ist, wie findet die Komponente unter Zuhilfenahme welcher weiteren Informationen das Objekt?

bhenker 5. Jul 2011 14:30

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Wenn ich mich richtig erinnere werden diese Komponenten beim Laden der DFM zugewiesen.
Einfach mal nach FixupReferences in der Classes.pas suchen.
Wird so auf eine Datenquelle in einem externen Datenmodul verwiesen, wird das über die globale Variable des Datenmodule in der jeweiligen Unit aufgelöst.
Deshalb sollte diese Variable zur Laufzeit auch belegt sein. Das wird in der Regel im Project mit "Application.CreateForm(MyDataModule, DMyDataModule)" auch erledigt.
Wenn mann das globale Erstellen dieser Module nicht durchführt, muß man schon selbst dafür sorgen das es erstellt wird.

RSE 5. Jul 2011 14:51

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Wie geschrieben, gibt es diese globale Variable bei mir nicht. Das Datenmodul wird "von Hand" im Konstruktor von MyForm erzeugt. Deswegen wundere ich mich ja, wie es trotz allem noch funktioniert.

FixupReferences gibt es dort einige, und ich verstehe nur Bahnhof...

Stevie 5. Jul 2011 19:57

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Das ganze könnte man als Bug bezeichnen, denn wenn du dir zur Laufzeit mal anschaust, ob MyDBEdit.DataSource assigned ist, wirst du feststellen, dass dies nicht der Fall ist. Die IDE nimmt einfach nur den Klassennamen des DataModules und streicht das T weg.

Wenn du mal händisch den Namen der globalen DataModule variable änderst, wirst du feststellen, dass dies dann auch passiert.
Korrektur: Das lag bei mir nur daran, dass ich dann keine Instanz des DataModules hatte - siehe meinen Post weiter unten.

Hansa 6. Jul 2011 02:28

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zitat:

Zitat von schlecki (Beitrag 1110022)
hm, da ich nicht soo viel visuell arbeite, ist mir das eigentlich gleich :)

Was hat visuell mit Sichtbarkeiten von Variablen + Co. zu tun ? :shock: Obwohl, vom Wort her könte man das eventuell schon vermuten. :mrgreen:

Zur Frage an sich : das geht schon sehr, sehr tief in die Eingeweide von Delphi rein. Solche Fragen werden sich hier kaum lösen lassen. Zumindest, wenn man mal folgendes bedenkt : die einzige mir bekannte Quelle, wo das Verhalten, IDE/Laufzeit in punkto DB-Komponenten näher erläutert wird, das sind Marco Cantus Bücher. Und sogar der braucht ca. 10-50 Buchseiten, je nachdem wo man anfängt. :mrgreen:

Zitat:

Zitat von RSE (Beitrag 1110091)
Das Datenmodul wird "von Hand" im Konstruktor von MyForm erzeugt. Deswegen wundere ich mich ja, wie es trotz allem noch funktioniert.

Warum wird das denn überhaupt von Hand erzeugt ? Welchen Sinn macht das denn ? Ich erzeuge etliches zur Laufzeit, aber auf die Idee, ein Datamodul so zu erzeugen bin ich noch nicht gekommen, das macht einfach nur Ärger. Siehe diesen Thread hier.

schlecki 6. Jul 2011 06:50

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zitat:

Zitat von Hansa (Beitrag 1110204)
Zitat:

Zitat von schlecki (Beitrag 1110022)
hm, da ich nicht soo viel visuell arbeite, ist mir das eigentlich gleich :)

Was hat visuell mit Sichtbarkeiten von Variablen + Co. zu tun ? :shock: Obwohl, vom Wort her könte man das eventuell schon vermuten. :mrgreen:

Mir ging es hier nur um den Unterschied public vs. published

RSE 6. Jul 2011 08:19

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zitat:

Zitat von Stevie (Beitrag 1110168)
Das ganze könnte man als Bug bezeichnen, denn wenn du dir zur Laufzeit mal anschaust, ob MyDBEdit.DataSource assigned ist, wirst du feststellen, dass dies nicht der Fall ist.

Widerlegung:
Delphi-Quellcode:
procedure TMyCustomForm.MyDBEditClick(Sender: TObject);
begin
  if MyDBEdit.DataSource = nil then
    Exit;
  Showmessage(MyDBEdit.DataSource.Owner.ClassName); // Rückgabe: "TMyDM"
end;
Zitat:

Zitat von Stevie (Beitrag 1110168)
Die IDE nimmt einfach nur den Klassennamen des DataModules und streicht das T weg.

Das habe ich mir auch so zusammengereimt. Das, was dann dabei rauskommt + Name der DS kann man im OI in die Eigenschaft DataSource eintragen. Dann hat man mein Verhalten.
Zitat:

Zitat von Hansa (Beitrag 1110204)
Zitat:

Zitat von RSE (Beitrag 1110091)
Das Datenmodul wird "von Hand" im Konstruktor von MyForm erzeugt. Deswegen wundere ich mich ja, wie es trotz allem noch funktioniert.

Warum wird das denn überhaupt von Hand erzeugt ? Welchen Sinn macht das denn ?

Die Bezeichner, die ich hier verwende sind beispielhaft gewählt (wer hätte das vermutet?). Das Originalprojekt besteht aus hunderttausenden Quelltextzeilen. Es gibt ein Grundprogramm, in das verschiedene Projekte integriert werden. In jedem Projekt gibt es ein DM und ein ProjektForm. Es ist immer nur ein Projekt instanziert, lassen wir auch die Projekt-DMs nicht automatisch bei Programmstart erzeugen. In das ProjektForm werden mehrere Frames geladen, die mehrere Seiten ergeben (das wäre dann der Inhalt des Projekts). Ein Projekt besteht aus 10.000-15.000 Quelltextzeilen. Beim Anlegen neuer Projekte wird ein altes Projekt kopiert und entsprechend der Anforderungen des neuen Projekts abgeändert. Bitte diskutiert jetzt nicht über das Design der Anwendung, das steht seit vielen Jahren fest und kann nicht problemlos geändert werden. Diskussionen darüber sind daher zwecklos.

Früher haben wir mit den globalen Variablen gearbeitet, die Delphi uns vorgegeben hat. Das hatte zur Folge, dass das DM in jedem Projekt unter anderem Namen erreichbar war. D.h. bei jeder Übernahme von Quelltextpassagen aus anderen Projekten musste jede Referenz auf das DM per Suchen und Ersetzen ausgetauscht werden. In einem ersten Schritt haben wir also die Variable einheitlich genannt (ProjektDM). Wir haben uns nix weiter dabei gedacht und es funktioniert prima.

Nun habe ich eine projektübergreifende Superklasse für das DM und das ProjektForm entworfen. Das entspricht nun genau meinem komplexeren Beispiel, über das hier nun diskutiert wird.

stahli 6. Jul 2011 08:35

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Hmm, mal ein paar Überlegungen:

Was bringt denn:
Delphi-Quellcode:
Showmessage(MyDBEdit.DataSource.Owner.Name);
Showmessage(MyDBEdit.DataSource.Name);
FindComponent('MyCustomDM')...
Kann es denn sein, dass Du in Deinem Demobeispiel maßgebliche Variablen Deines echten Projektes "unterschlägst", dass also tatsächlich irgendwo eine solche Variable definiert ist?

Kannst Du Deinen Demotext mit vertretbarem Aufwand in ein echtes Projekt gießen und live testen?
Dann könnten wir das vielleicht auch mal genauer nachvollziehen...

RSE 6. Jul 2011 08:59

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Zitat:

Zitat von stahli (Beitrag 1110222)
Hmm, mal ein paar Überlegungen:

Was bringt denn:
Delphi-Quellcode:
Showmessage(MyDBEdit.DataSource.Owner.Name);
Showmessage(MyDBEdit.DataSource.Name);
FindComponent('MyCustomDM')...

1. "MyDM"
2. "MyDS"
3. nil
Das scheinen mir alles sehr korrekte Werte zu sein...
Zitat:

Zitat von stahli (Beitrag 1110222)
Kann es denn sein, dass Du in Deinem Demobeispiel maßgebliche Variablen Deines echten Projektes "unterschlägst", dass also tatsächlich irgendwo eine solche Variable definiert ist?

Ich habe das ganze Projekt durchsucht: Es kommt TMyCustomDM, UMyCustomDM (Der Klassenname ohne T ist im Originalprojekt Teil des Unitnamens - Fehler im ersten Beitrag) und in der DPR etwas wie "UMyCustomDM in 'pfad\UMyCustomDM.pas' {MyCustomDM: TDataModule},". Die Zeile in der DPR ist also der einzige Ort im ganzen Projekt (abgesehen von DFMs), in dem der Bezeichner MyCustomDM vorkommt, und dort tut er es nur in einem Kommentar.
Zitat:

Zitat von stahli (Beitrag 1110222)
Kannst Du Deinen Demotext mit vertretbarem Aufwand in ein echtes Projekt gießen und live testen?
Dann könnten wir das vielleicht auch mal genauer nachvollziehen...

Ich probiere mal, inwieweit das ohne tatsächliche DB-Anbindung ausführbar ist und hänge es ggf. hier an einen Beitrag von mir an.

stahli 6. Jul 2011 09:14

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
"UMyCustomDM in 'pfad\UMyCustomDM.pas' {MyCustomDM: TDataModule},"

Ich weiß es nicht wie der Compiler genau vorgeht, aber vielleicht wertet er ja diesen "Kommentar" irgendwie aus und erzeugt beim Öffnen des Projektes eine passende Variable - eben zur Herstellung der Projektverbindungen. Ist nur Spekulation - wäre aber ja denkbar.

Ändere doch mal testweise den Kommentar in {MyCustomDMXxx: TDataModule}.

Wenn es dann nicht mehr funktioniert, hätte man eine Erklärung...

RSE 6. Jul 2011 09:42

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Ich habe jetzt mal mein Beispiel implementiert... :pale: und es läuft nicht. :shock: Baue ich in das Originalprojekt genau die selbe DS und das selbe DBEdit ein, klappt es. :shock: Somit ist dem Thread gerade die Diskussionsgrundlage entzogen worden...
Ich werde mich auf die Suche machen und mich dann wieder melden. :oops:

Stevie 6. Jul 2011 09:54

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Liste der Anhänge anzeigen (Anzahl: 1)
Du kannst in deinem uns nicht vorliegenden Projekt gern widerlegen, was ich sagte, es stimmt dennoch. Erzeugst du allerdings irgendwo eine Instanz dieses DataModules, wird diesem DataModule ein Name verpasst (rat mal welcher) und sie wird gefunden, wenn die Form aus der dfm geladen wird bzw wenn dieses ominöse GlobalFixupReferences aufgerufen wird (Tip: kompilier mit debug dcus und setz nen Stoppunkt in TDBEdit.SetDataSource)

Die Identifizierung der Komponenten, die in der dfm einander zugewiesen werden, geschieht anhand des Namens.

Siehe Anhang

stahli 6. Jul 2011 10:27

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Liste der Anhänge anzeigen (Anzahl: 1)
Oha!

Also mit dem DataModuleName stimmt. Siehe Code + ScreenShot.

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  DM2a, DM2b: TDataModule2;
begin
  DM2a := TDataModule2.Create(Application);
  Caption := Caption + '->' + DM2a.Name;
  DM2b := TDataModule2.Create(Application);
  Caption := Caption + '->' + DM2b.Name;
end;
Dann sollte aber FindComponent die Komponente finden...

Ich steige hier aus und warte auf einen Abschlussbericht des TE ;-)

RSE 6. Jul 2011 14:07

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, das Beispielprojekt ist fertig. Ihr findet es im Anhang.

stahli 6. Jul 2011 16:13

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Liste der Anhänge anzeigen (Anzahl: 2)
So ganz habe ich das nicht durchblickt, aber ein DataModule schaut beim erzeugen sofort nach, ob es sich irgendwo einklinken (aufdrängeln ;-) ) kann.
In der Konsequenz sollte das zur Folge haben, dass man nicht zwei DataModules mit gleichen Komponenten verwenden kann.
Na ja, es ist etwas verworren.

Im Projekt habe ich mal die Functionen aus Classes.pas herauskopiert und Breakpoints gesetzt. Die Überwachung der globalen DBEdit "E" zeigt dann, wann E ein DataSet zugewiesen wird.

DataSet toleriert dabei, dass der aktuelle Klassentyp nicht mehr TMyCustomDM ist (oder so ähnlich :freak:).

Stevie 6. Jul 2011 16:43

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
In UMyCustomForm ist die Unit UMyCustomDM eingebunden. Deshalb kannst du dort im MyDBEdit unter DataSource MyCustomDM.MyDS eintragen.

TMyForm ist von TMyCustomForm abgeleitet und erbt auch die Einstellungen aus der dfm des Vorfahren.

Beim Laden des Forms wird dann für den Wert MyCustomDM.MyDS ein GlobalFixup gespeichert und hinterher, wenn du TMyDM erstellst und zuweist, sorgt GlobalFixupReferences dafür, dass an den Stellen, wo diese Referenz über den Designer zugewiesen wurde, die neue Referenz zugewiesen wird.

RSE 6. Jul 2011 17:49

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
@ stahli: Die von dir angesprochene Zeile
Delphi-Quellcode:
Instance := ReadComponent(Instance); // <----------------------------------
lädt das Datamodule aus der DFM. Da passiert noch nichts weiter bzgl. der Verknüpfung zwischen DM und DBEdit. Erst nachdem ich mich in diesen Aufruf weiter reindebuggt habe, bin ich auf die von Stevie angesprochene Funktion Classes.GlobalFixupReferences gestoßen. Diese ruft wiederum Forms.FindGlobalComponent auf.

Und bei diesen 2 letzten Funktionen wird es interessant: Nach jeder Erstellung einer Form oder eines Datenmodules werden Verknüpfungen von Controls (wie meinem DBEdit) auf andere Forms und Datenmodule aufgelöst, und zwar basierend auf der Eigenschaft Name. Das ganze wird auf Basis von Screen.Forms und Screen.DataModules durchgeführt. Das interessante dabei: Bei meiner Instanzierung von MyDM wird zuerst eine Instanz von TMyCustomDM aus dem DFM gelesen (mit Name = MyCustomDM, wie in UMyCustomDM.dfm angegeben). Gibt es noch nicht aufgelöste Verknüpfungen/Referenzen (wie bei der DataSource-Property meines DBEdits), dann werden diese gesucht (und in meinem Fall gefunden: Name = MyCustomDM, wie im DBEdit angegeben). Anschließend wird über die Instanz von TMyCustomDM die Instanz von TMyDM "drübergelesen" - hier wird der Name mit MyDM überschrieben, was dann zur Laufzeit angezeigt wird.

Quintessenz: Die ganze Verknüpfung basiert nicht auf der evtl. nicht vorhandenen globalen Variable, wie Anfangs vermutet wurde, sondern auf der Eigenschaft Name. Und: Name wird für jede einzelne Vererbungsebene geprüft (im Beispiel zuerst MyCustomDM und dann MyDM).

Ergo: Dass diese Verknüpfung von DBEdit und MyCustomDM funktioniert, ist nicht nur zufällig und ich kann mich darauf verlassen, dass es immer funktioniert. Ich muss sagen, das ist ein cleveres System, was sich die Designer da ausgedacht haben!

p.s.: Erklärung von FindGlobalComponent auf englisch: http://www.blong.com/Conferences/DCo...#_Toc485725936

stahli 7. Jul 2011 08:40

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Na dann wissen wir ja "bescheid".
Es ist aber doch recht überraschend, wie das im Detail umgesetzt ist.
Insb. dass dieses "binding" auch beim händischen Erzeugen eines DataModule erfolgt und dass auch die ParentClassTypes für die Zuordnung herangezogen werden.
Ich hätte jedenfalls damit so nicht gerechnet.

RSE 7. Jul 2011 09:01

AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
 
Es gibt noch eine Unwägbarkeit bei dem Ganzen: Ob das funktioniert, ist von der Erstellungsreihenfolge abhängig! Der Ablauf, den ich in meinem letzten Beitrag beschrieben habe, läuft nur dann so ab, wenn das DBEdit vor dem Datenmodul erstellt wird. Ansonsten sieht der Ablauf folgendermaßen aus:

Zuerst wird das Datenmodul erzeugt. Zu dieser Zeit bestehen keine nicht aufgelösten Abhängigkeiten. Nach der Erzeugung des Datenmoduls hat Screen.DataModules genau einen Eintrag: Ein Datenmodul mit Name "MyDM". Ein Datenmodul mit Name "MyCustomDM" hat nur während der Instanzierung von TMyDM kurzzeitig existiert. Wenn jetzt danach DBEdit instanziert wird, dann kann die Abhängigkeit "MyCustomDM.DS" nicht aufgelöst werden, da weder ein Formular noch ein Datenmodul mit Namen "MyCustomDM" existiert.

Man kann das im Beispielprojekt leicht testen, wenn man den Konstruktor von TMyForm folgendermaßen umbaut (Das Datenmodul vor dem inherited-Aufruf instanziert):
Delphi-Quellcode:
constructor TMyForm.Create(AOwner: TComponent);
begin
  SetDM(TMyDM.Create(Self)); //wenn Owner freigegeben wird, wird DM automatisch mit freigegeben
  inherited;
end;
In dem Fall kann die Abhängigkeit nicht mehr aufgelöst werden und beim Klick auf DBEdit kommt die Meldung "nil".


Ein weiterer Fallstrick:

Instanziert man anschließend (z.B. per Buttonclick) eine weitere Instanz von TMyDM, dann wird die Abhängigkeit von DBEdit auf diese Instanz aufgelöst.


Ergo:

Abhängigkeiten zu Formularen/Datenmodulen , die niemals selbst instanziert werden (nur davon abgeleitete Klassen werden instanziert) sind mit Vorsicht zu genießen, da sie immer auf das erste passende Formular/Datenmodul aufgelöst werden, das nach dem Control instanziert wird. Somit ist die Erstellungsreihenfolge von entscheidender Bedeutung.

Mein Vorschlag, um diese Probleme zu umgehen:

In den Fällen, in denen Abhängigkeiten zu Datenmodulen notwendig sind, die nicht direkt instanziert werden (sondern nur deren Nachkommen), sowie bei Datenmodulen, die mehrfach instanziert werden (wobei mir dazu grad kein Anwendungsfall einfällt), sollte folgendermaßen vorgegangen werden: Auf der Form mit den DB-Controls liegt ein (oder mehrere) entsprechendes Datasource, welches bei der Instanzierung der Form mit der Query aus dem DM verbunden wird (Das DM muss also zwingend vorher instanziert worden sein). Somit gibt es keine zur Designtime definierten Abhängigkeiten mehr, deren Auflösung die Probleme verursacht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:55 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