Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Unit "dynamisch" einbinden (https://www.delphipraxis.net/181271-unit-dynamisch-einbinden.html)

ernschd 31. Jul 2014 15:12

Delphi-Version: 2007

Unit "dynamisch" einbinden
 
Folgendes Problem:
Ich habe eine Unit „Les“:
Delphi-Quellcode:
Unit Les;

Procedure LeseDatei(Name: String);
begin
   AssignFile(Name…
end;
Dann gibt es die Unit „LesSQL“:
Delphi-Quellcode:
Unit LesSQL;

Procedure LeseDatei(Name: String);
begin
   Sql := „SELECT * FROM `Name`…
end;
Die Methodenaufrufe der Unit LesSQL wurden aus Gründen der Kompatibilität identisch mit denen der Les erstellt. Die beiden Dateien sollten auch so erhalten bleiben.
Bislang wurden die Units immer je nach Anwendungsfall eingebunden und kompiliert.

Nun gibt es eine neue Klasse „TLese“ als Wrapper, die den Zugriff auf die Les/LesSQL-Units vereinfacht:
Delphi-Quellcode:
// LeseDatei aufrufen.
Function TLese.getDatei: Boolean;
Ich hätte nun gerne eine Möglichkeit, je nach Anwendungsfall die passende Unit in der Klasse TLese einzubinden (z.B. mittels Parameter im Konstruktor).
Gibt es hierfür eine Lösung? Vielleicht per Compiler-Direktive?

mkinzler 31. Jul 2014 15:16

AW: Unit "dynamisch" einbinden
 
Könnte man durch bedingte Compilierung lösen

Delphi-Quellcode:
uses
   ...,
{$IFDEF USE_SQL} LesSQL{$ELSE}Les{$ENDIF}, ...

DeddyH 31. Jul 2014 15:18

AW: Unit "dynamisch" einbinden
 
Aber das funktioniert nur zur Designtime und nicht durch Konstruktor-Parameter oder ähnliches.

Bernhard Geyer 31. Jul 2014 18:53

AW: Unit "dynamisch" einbinden
 
Schlagworte wären hier Bridge Pattern oder Abstract Factory

Der schöne Günther 31. Jul 2014 19:02

AW: Unit "dynamisch" einbinden
 
Soweit ich das verstehe ist doch das eigentliche Problem, dass Delphi es nicht erlaubt, eine "Unit an sich" zu referenzieren- Es gibt keinen Typ dafür. Somit kann man nicht dynamisch sagen "Unit A" oder "Unit B".

Da beide Units doch schon so schön aufgebaut sind, wäre es doch eigentlich die geringste Arbeit, die beiden endlich in eine Klasse mit gemeinsamer Schnittstelle zu packen, oder?
Alternativ je eine Klasse (wieder mit gemeinsamer Schnittstelle) als Fassade für eine Unit wenn man die alte Unit-Struktur noch woanders verwenden möchte.

nuclearping 31. Jul 2014 19:43

AW: Unit "dynamisch" einbinden
 
Du kannst die Funktionen in
Delphi-Quellcode:
Les
und
Delphi-Quellcode:
LesSQL
in Klassen auslagern. Zum Beispiel kannst du hier auch auf Vererbung zurückgreifen.

Delphi-Quellcode:
unit LesBase;

interface

type
  TLesBase = class
  public
    function LeseDatei(Name: String): String; virtual; abstract;
  end;

  TLesBaseClass = class of TLesBase;

implementation

end.
Delphi-Quellcode:
unit Les;

interface

uses
  LesBase;

type
  TLes = class(TLesBase)
  public
    function LeseDatei(Name: String): String; override;
  end;

implementation

function TLes.LeseDatei(Name: String): String;
begin
  ...
end;

end.
Delphi-Quellcode:
unit LesSQL;

interface

uses
  LesBase;

type
  TLesSQL = class(TLesBase)
  public
    function LeseDatei(Name: String): String; override;
  end;

implementation

function TLesSQL.LeseDatei(Name: String): String;
begin
  ...
end;

end.
Und in dem Wrapper kannst du dann im Constructor die entsprechende Les-Klasse übergeben.

Delphi-Quellcode:
unit Lese;

interface

uses
  LesBase;

type
  TLese = class
    constructor Create(ALesClass: TLesBaseClass);
    destructor Destroy; override;
  private
    FLesClass: TLesBaseClass;
  public
    function getDatei: Boolean;
  end;

implementation

constructor TLese.Create(ALesClass: TLesBaseClass);
begin
  FLesClass := ALesClass.Create;
end;

destructor TLese.Destroy;
begin
  FLesClass.Free;
  inherited;
end;

function TLese.getDatei: Boolean;
begin
  Result := Length(FLesClass.LeseDatei('...') > 0);
end;

end.
Anwendung:
Delphi-Quellcode:
unit Form1;

interface

...

implementation

uses
  Lese, Les, LesSQL;

...

procedure TForm1.Button1Click(Sender: TObject);
var
  LesClass: TLesBaseClass;
begin
  case FUseClass of
    clLes:
      LesClass := TLes;
    clLesSQL:
      LesClass := TLesSQL;
  end;
  FLese := TLese.Create(LesClass);
  try
    if FLese.getDatei then
      ShowMessage('Juhu! \o/')
    else
      ShowMessage('Oh Noes! D:');
  finally
    FLese.Free;
  end;
end;

...

end.
Ungetestet. Aber das Prinzip sollte klar sein. :thumb:

ernschd 1. Aug 2014 11:54

AW: Unit "dynamisch" einbinden
 
So weit mal vielen Dank an alle :)

Ich schaue mir mal an, wie ich das umsetzen kann.

Bernhard Geyer 1. Aug 2014 13:08

AW: Unit "dynamisch" einbinden
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1267217)
Soweit ich das verstehe ist doch das eigentliche Problem, dass Delphi es nicht erlaubt, eine "Unit an sich" zu referenzieren- Es gibt keinen Typ dafür. Somit kann man nicht dynamisch sagen "Unit A" oder "Unit B".

Über Packages (und eigentlich wieder Klassen/Interfaces) wäre das möglich.
Ich würde das aber nicht empfehlen das dynamisch darüber zu machen.

Ebenfalls wäre ein reine DLL möglich die jeweils die gleichen exportierten Funktionen hat.


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