Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zirkuläre Referenzen (https://www.delphipraxis.net/207180-zirkulaere-referenzen.html)

lxo 2. Mär 2021 07:32

Delphi-Version: 10.4 Sydney

Zirkuläre Referenzen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

gibt es noch andere Wege eine zirkuläre Unit-Referenz zu vermeiden für diesen Anwendungsfall? (siehe Anhang)
Am einfachsten wäre ja sonst im Implementation-Uses-Block der Unit uChildForm, uMainForm einzutragen.
Damit hätte ich dann aber eine zirkuläre Unit-Referenz.

Um dies zu vermeiden, könnte man das ja auch wie im Beispiel mit Events machen.
Gibt es noch andere Möglichkeiten?

jziersch 2. Mär 2021 08:43

AW: Zirkuläre Referenzen
 
Du kannst ein Interface entwickeln welches Du in einer globalen unit definierst, die keine andern Units einbindest. Dieses Interface implementierest Du dann für das Objekt, das die jeweilige Operation ausführst.

Eintragen im Implementation fall geht zwar, hat aber negative Auswirkung auf die Versionskontrolle (welche unit wurde verändert und muss neu erstellt werden) und, soweit ich weiß, auf die Compilierzeit.

lxo 2. Mär 2021 09:10

AW: Zirkuläre Referenzen
 
Zitat:

Zitat von jziersch (Beitrag 1484230)
Du kannst ein Interface entwickeln welches Du in einer globalen unit definierst, die keine andern Units einbindest. Dieses Interface implementierest Du dann für das Objekt, das die jeweilige Operation ausführst.

Eintragen im Implementation fall geht zwar, hat aber negative Auswirkung auf die Versionskontrolle (welche unit wurde verändert und muss neu erstellt werden) und, soweit ich weiß, auf die Compilierzeit.

Tut mir leid, ich versteh nicht genau wie ich das umsetzen sollte ohne eine zirkuläre Referenz.
Hättest du da evtl. ein Beispiel?

himitsu 2. Mär 2021 09:28

AW: Zirkuläre Referenzen
 
Unit3 enthält die Interfacedeklaration (praktisch könnte auch jeder seine egene Interfacedeklaration benutztn, so lange sie "gleich" sind, dann braucht man keine dritte Unit)
und dann verwenden beide Units 1 und 2 dieses Interface und schon haben sie unterienander keinerlei Abhängigkeiten mehr.

Rollo62 2. Mär 2021 09:31

AW: Zirkuläre Referenzen
 
Interfaces können auch mit Forms, Frames, DataModules etc. genutzt werden.

Delphi-Quellcode:
type
  IMyMainForm_Interface = interface
    [GUUID]
    procedure OpenMainForm(Sender: Tobject);
  end;

...
...
...

type
  TTMainForm = class(TForm, IMyMainForm_Interface )
...
    procedure OpenMainForm(Sender: Tobject);
  end;

lxo 2. Mär 2021 09:35

AW: Zirkuläre Referenzen
 
Zitat:

Zitat von Rollo62 (Beitrag 1484239)
Interfaces können auch mit Forms, Frames, DataModules etc. genutzt werden.

Delphi-Quellcode:
type
  IMyMainForm_Interface = interface
    [GUUID]
    procedure OpenMainForm(Sender: Tobject);
  end;

...
...
...

type
  TTMainForm = class(TForm, IMyMainForm_Interface )
...
    procedure OpenMainForm(Sender: Tobject);
  end;

Aber wie kann ich jetzt im uChildForm das MainForm öffnen ohne dies einzubinden?
Irgendwie versteh ich das gerade nicht.

TiGü 2. Mär 2021 10:02

AW: Zirkuläre Referenzen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Siehe Anhang. Ein skizzenhaftes Beispiel, ist natürlich verbesserungswürdig.

jziersch 2. Mär 2021 10:03

AW: Zirkuläre Referenzen
 
[/QUOTE]
Aber wie kann ich jetzt im uChildForm das MainForm öffnen ohne dies einzubinden?
Irgendwie versteh ich das gerade nicht.[/QUOTE]

In der globalen Unit (die braucht man dann doch) definierts Du eine globale interface referenz.

In MainForm im OnCreate weist Du dies dann auf "Self" zu.

Im Child fragst Du die Variable ab und kannst Deine Prozedur aufrufen.

Alternativ kann natürlich jedes Child diese Variable haben und diese wird beim Erstellen gesetzt, sozusagen der "Owner"

Edit: Der Vorschlag von TiGÜ implementiert dies - sogar für das Child.

lxo 2. Mär 2021 10:22

AW: Zirkuläre Referenzen
 
Zitat:

Zitat von jziersch (Beitrag 1484249)

In der globalen Unit (die braucht man dann doch) definierts Du eine globale interface referenz.

In MainForm im OnCreate weist Du dies dann auf "Self" zu.

Im Child fragst Du die Variable ab und kannst Deine Prozedur aufrufen.

Alternativ kann natürlich jedes Child diese Variable haben und diese wird beim Erstellen gesetzt, sozusagen der "Owner"

Edit: Der Vorschlag von TiGÜ implementiert dies - sogar für das Child.

Ok das hab ich verstanden.
Ist aber nicht so wie ich es mir vorgestellt habe.
Mit der Lösung kann ich nur mit jeweils einer Instanz von MainForm oder ChildForm arbeiten.

Beim Öffnen möchte ich jedoch immer eine neue Instanz erzeugen.

Uwe Raabe 2. Mär 2021 10:24

AW: Zirkuläre Referenzen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier noch eine Lösung auf Basis von System.Messaging.

lxo 2. Mär 2021 10:27

AW: Zirkuläre Referenzen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1484252)
Hier noch eine Lösung auf Basis von System.Messaging.

:thumb: genau sowas hab ich gesucht, danke !

lxo 2. Mär 2021 13:16

AW: Zirkuläre Referenzen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1484252)
Hier noch eine Lösung auf Basis von System.Messaging.

Sehr coole Lösung.
Eine Frage hätte ich da aber noch.
Wie würdest du vorgehen, wenn man für das Open der Form noch Parameter mitgeben möchte und auch ein Result zurück bekommen möchte?

Also ich habe da was, bin mir aber nicht sicher ob das die eleganteste Lösung ist.

Delphi-Quellcode:
  TMainFormParameter = class
    ParameterIN,
    ParameterOUT: String;
  end;
  TMainFormMessage = class( TMessage< TMainFormParameter>);

  TChildFormParameter = class
    ParameterIN,
    ParameterOUT: String;
  end;
  TChildFormMessage = class( TMessage< TChildFormParameter>);

.....

  var lParameter := TChildFormParameter.Create;
  try
    lParameter.ParameterIN := 'Ich komme aus MainForm und gebe dies als Parameter mit';
    TMessageManager.DefaultManager.SendMessage( Sender, TChildFormMessage.Create( lParameter));
  finally
    ShowMessage( lParameter.ParameterIN + sLineBreak +
                 lParameter.ParameterOUT);
    lParameter.Free;
  end;
Aufgrund von "const M: TMessage", könnte ich Records nur als Konstante-Parameter mitgeben oder könnte man das auch irgendwie mit Records machen?

TiGü 2. Mär 2021 14:15

AW: Zirkuläre Referenzen
 
Delphi-Quellcode:
procedure TTMainForm.Button1Click(Sender: TObject);
var
  Msg: TOpenChildFormMessage;
begin
  Msg := TOpenChildFormMessage.Create;
  Msg.ParameterIN := 'Ich komme aus MainForm und gebe dies als Parameter mit';
  TMessageManager.DefaultManager.SendMessage(Self, Msg, False); // das False ist wichtig!
  ShowMessage(Msg.ParameterOut);
  Msg.Free;
end;
Delphi-Quellcode:
 
TOpenChildFormMessage = class(TMessage)
  public
    ParameterIN,
    ParameterOUT: String;
  end;
Delphi-Quellcode:
procedure MsgOpenChildForm(const Sender: TObject; const M: TMessage);
var
  Msg: TOpenChildFormMessage;
begin
  if M is TOpenChildFormMessage then
  begin
    Msg := TOpenChildFormMessage(M);
    ShowMessage(Msg.ParameterIN);
    TChildForm.OpenChildForm(Sender);
    Msg.ParameterOut := 'Hallo Welt!';
  end;
end;
Mit records ist auch möglich, dann musst du dir die Instanz auch merken und auf dein Record per TChildFormMessage.Value (Value ist dann der generische Typ) zugreifen.

lxo 2. Mär 2021 14:40

AW: Zirkuläre Referenzen
 
:thumb:
Vielen Dank, da hab ich bisschen zu kompliziert gedacht.


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