![]() |
Re: Implementation Interface Struktur
Zitat:
Aber wenn er eben im Programm z.B. mit Supports prüfen will, ob es wirdklich ein "Pulgin"-Interface ist, dann braucht er schon eine einheitliche IID. |
Re: Implementation Interface Struktur
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
ich habe heute Morgen die entsprechenden Routinen mal als Sample ohne "drumherum" in ein Projekt gepackt; mein Stand ist noch wie gestern Abend :pale: . Ich möchte die "Plugins" gerne mit Units verwenden, nicht mit DLLs und weiss immer noch nicht so recht, wo das "gibmirdasinterface" reinkommt. Wäre toll, wenn jemand einen Blick werfen würde. lg Sebastian |
Re: Implementation Interface Struktur
Bei Units brauchst du nicht zwingend eine Funktion "GibMirDasInterface". Bei Units sind anstatt Interfaces auch eher abstrakte Klassen geeignet (in Delphi).
In einer DLL brauchst du "GibMirDasInterface", weil du sonst die Klasse nicht erstellen kannst. Den Verweis auf die beiden Units kannst du nicht verhindern (wo du "unschön" hinschriebst). Ansonsten sieht dein Programm doch ok aus. Wo hakt es denn noch? |
Re: Implementation Interface Struktur
Hi,
Zitat:
Zitat:
Zitat:
Die zweite Frage ist, ob man das "Durchschleifen" der Parameter mittels "SetParameter" besser machen kann und die dritte wäre, ob sich das "if" Verzweigung in der procedure "SetParameter" besser lösen lässt - gibt es sowas wie "Var(paramname):=value" ? lg Sebastian |
Re: Implementation Interface Struktur
Ich könnte mir das etwa so vorstellen:
Delphi-Quellcode:
Implementation:
type
IExport = interface procedure Export({...}); function GetParams: TStringList; procedure SetParams(AValue: TStringList); property Params: TStringList read GetParams write SetParams; end;
Delphi-Quellcode:
Ohne das die Anwendung die Parameter der konkreten Schnittstelle kennen muss, können die Parameter so vom Anwender bearbeitet, gespeichert und gelesen werden. TStringList ist natürlich nur die einfachste Variante. Denkbar wäre eine Liste von Parameterobjekten die jeweils noch weitere Information über die Art des Paramaters besitzen und diesen validieren können.
procedure CreateExport: IExport; export;
implementation type TExportCSV = class(TInterfacedObject, IExport) protected FParams: TStringList; procedure InitParams; virtual; procedure CheckParams; virtual; public {IExport} procedure Export({...}); function GetParams: TStringList; procedure SetParams(AValue: TStringList); public constructor Create; destructor Destroy; override; end; constructor TExportCSV.Create; begin inherited; FParams := TStringList.Create; InitParams; end; destructor TExportCSV.Destroy; begin FParams.Free; inherited; end; procedure TExportCSV.InitParams; begin {alle möglichen Parameter mit default eintragen} with FParams do begin Add('ExportDir' + NameValueSeparator); Add('Separator' + NameValueSeparator + ';'); {...} end; end; procedure TExportCSV.CheckParams; begin if FParams.Values['ExportDir'] = '' then raise Exception.Create('Parameter ''ExportDir'' ist erforderlich.'); if FParams.Values['Separator'] = '' then raise Exception.Create('Parameter ''Separator'' ist erforderlich.'); if Length(FParams.Values['Separator']) > 1 then raise Exception.Create('Parameter ''Separator'' darf nur ein Zeichen enthalten.'); {...} end; procedure TExportCSV.SetParams(AValue: TStringList); begin FParams.Assign(AValue); end; function TExportCSV.GetParams: TStringList; begin Result := FParams; end; procedure TExportCSV.Export({...}); begin CheckParams; {...} end; procedure CreateExport: IExport; begin Result := TExportCSV.Create; end; |
Re: Implementation Interface Struktur
Liste der Anhänge anzeigen (Anzahl: 1)
Hi !
Zitat:
Aber auf eine Lösung folgt das nächste Problem. Ich habe die Übergabe der Variablen aus dem Hauptprogramm nun so (funktioniert) :
Delphi-Quellcode:
Ich würde aber gerne so etwas wie
var myParams: TStringList;
...... myParams:=TStringList.Create; myParams.Add('ExportDir'+myParams.NameValueSeparator+'SAMPLE'); SetLength(myExport, 1); myExport[0]:=TExportCSV.Create; myExport[0].Params:=myParams; .... myParams.Free;
Delphi-Quellcode:
verwenden. Das funktioniert aber nicht ?!
myExport[0].Params.Add('Separator=;');
Bei einem Trace geht er in TExportCSV.GetParams rein und nicht in die SetParams. Ich habe das Projekt nochmal angehängt. lg |
Re: Implementation Interface Struktur
GetParams ist schon richtig, wenn mit der Stringliste der Exportklasse gearbeitet wird.
SetParams ist eigentlich überflüssig, entspricht GetParams.Assign().
Delphi-Quellcode:
Edit:
myExport[0].Params.Values['Separator'] := ';';
{oder} with myExport[0].Params do begin Values['Separator'] := ';'; {...} end; Im Prinzip würde auch Add funktionieren, allerdings wäre der Parameter dann vieleicht doppelt vorhanden. |
Re: Implementation Interface Struktur
Zitat:
TStringList ist eine Delphiklasse und würde es erzwingen dass Exe und DLL mit gleichen Runtime-Packages ausgeliefert werden. Und wie wir das schon letztlich hatten, kann man sich dann die DLL gleich schenken. Die Zeit für dieses Pseudo-Modularisieren kann auch sinnvoller verschwenden. Mit Däumchendrehen zum Beispiel. IMO macht würde es mehr Sinn machen, wenn das Interface eine Methode zum Setup eines Exports anbietet. also sowas
Delphi-Quellcode:
Die jeweilige Export Implementierung könnte jetzt zum Beispiel einen Dialog zum Speichern der Datei anbieten, oder fragen in welchen Characterset der Export erfolgen soll.
type
IExport = interface(IUnknown) ['...'] function ExecuteModal({...}) : TModalResult; safecall; procedure ExecuteFromSettings({...}); safecall; procedure Initialize(const host : IHost); safecall; end; Wenn das ganze automatisierbar und wiederholbar sein sollte, sollte es zusätzlich neben den reinen Benutzer-getriebenen Modus auch die Möglichketi geben, dass er die Werte ablegt. Allerdings machtes IMO wenig Sinn das von außen durch den Host anzustoßen (die Stringlist). Der host soltle dem Plugin viel mehr einen Weg geben um Settings ablegen zu können. Das könnte ein IXmlDocument sein. Welches vom Host erzeugt und auch wieder gespeichert wird. Es gibt verschiedene Mittel mit denen der Host Funktionalität (nennen wir das mal einfach "Services") den PlugIns zur Verfügung stellen kann. Das erste (und simpelste) wäre, das es direkt Methoden und Properties des IHost interfaces sind.
Delphi-Quellcode:
Die Host-Anwendung würde für jedes Plugin solche eine IHost-Referenz anlegen, so dass ein Plugin nicht aus Versehen in den Sachen eines anderen rumschreibt.
type IHost = interface(IUnknown)
['...'] procedure GetSettings(out settings : IXmlDocument); safecall; procedure SaveSettings(const settings : IXmlDocument); safecall; end; Das ganze ist aber extrem unflexibel und führt fast zwangsläufig dazu, dass irgendwann das IHost-Interface erweitert werden muss, wodurch man entweder ein IHost2-Interface einführen müsste, oder bestehende Plugins würden nicht mehr laufen. Das wäre schlecht! Besser ist es die Services, die der Host (oder andere Plugins) zur verfügung stellen will auch als solche zu schreiben. Zum Biespiel der Service, für die Settings zuständig wäre:
Delphi-Quellcode:
Jetzt würde das Plugin so seine Settings holen:
type
ISettingsProvider = interface(IUnknown) ['...'] procedure GetSettings(out settings : IXmlDocument); safecall; procedure SaveSettings(const settings : IXmlDocument); safecall; end; IHost = interface(IUnknown) ['...'] function GetService(const serviceID : TGuid; out service : IUnknown) : Boolean; safecall; function RegisterService(const serviceID : TGuid; const service : IUnknown) : Boolean; safecall; end;
Delphi-Quellcode:
Du könntest aber die Anwendung erweitern und neue Services hinzufügen, ohne, dass dir rgendein Plugin um die Ohren fliegt, egal ob es 1 Tag oder 5 Jahre alt ist.
var
settingsService : ISettingsService; settings : IXmlDocument; tmp : IUnknown; begin if host.GetService(ISettingsService, out tmp) and Supports(tmp, ISettingsService, settingsService) then settingsService.GetSettings(settings) else settings := nil; if assigned(settings) then begin ... settingsService.SaveSettings(settings); end; end; Sogar andere Plugins könnten Services registrieren, die alle anderen PlugIns nutzen könnten. Plugins könnten auf die Weise in unterschiedlichen Delphiversionen oder sogar in C++ oder C# geschrieben werden. Du könntest also in C# einen Service schreiben, der allen Plugins deiner App RegExes zur Hand gibt, oder die Crypto APIs aus .Net, etc. |
AW: Implementation Interface Struktur
Hallo zusammen,
ich weiss - es ist schon ein wenig her, aber jetzt war eine Anpassung am Programm nötig und da habe ich mal weitergemacht ;-) Nachdem ich den Thread nochmals durchgearbeitet habe, habe ich mich entschieden, die Plugins über DLLs zu implementieren - und damit war auch "gibmirdasinterface" klar. Jetzt funktioniert alles. Vielen Dank für die vielen Anregungen, die auch fast alle eingeflossen sind ! Grüße, Sebastian |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:12 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 by Thomas Breitkreuz