Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Event in Interface vorgeben (https://www.delphipraxis.net/209689-event-interface-vorgeben.html)

Maliko 10. Jan 2022 12:49

Event in Interface vorgeben
 
Moin,

ich hab da momentan ein Problem, wo mir Google auch nicht wirklich bei weiter hilft. Und zwar habe ich ein Interface, welches wiederum von mehreren Klassen genutzt wird. Diese Klassen wiederrum werden in einem anderen Teil des Programmes verwendet indem eine Liste mit Objekten von diesem Interface durchlaufen werden und bei jedem Objekt wird eine bestimmte Methode verwendet. Allerdings habe ich jetzt das Problem dass ich auch noch ein Event brauche. Das Event selbst habe ich in der entsprechenden Klasse auch implementiert und das Funktioniert auch wenn ich die Klasse direkt aufrufe. Ich habe nur keine Ahnung wie ich dem Interface sage, dass alle Klassen die es nutzen dieses Event bitte implementieren müssen.

Folgenden Code habe ich:
Delphi-Quellcode:
  TOptionType = (otAuswertungsoptionen, otSonstigeOptionen, otAusgabeoptionen);

  TOnValidationError = procedure(const aErrorText : String) of object;

  IOptionLogic = interface
    ['{3E8091DE-BE13-4C88-9C2B-F0DF96F78AEE}']
    function GetOption : TPanel;
    function GetOptionType : TOptionType;
    function FirmaId : String;
    function UseOnlyOnFirmaId : Boolean;
    procedure ValidateOption;
  end;

  TStatistikAuswertungOption = class(TInterfacedObject, IOptionLogic)
    private
      FOwner : TComponent;
      FPanel : TPanel;
      FCreated : Boolean;
      FValidationErrorEvent : TOnValidationError;
      procedure chkBetraegeClick(Sender: TObject);
      procedure ckhPunktzahlenClick(Sender: TObject);
    protected
      procedure DoOnValidationError(const aErrorText : String);
    public
      property OnValidationError : TOnValidationError read FValidationErrorEvent write FValidationErrorEvent;
      function GetOption : TPanel;
      function GetOptionType : TOptionType;
      function FirmaId : String;
      function UseOnlyOnFirmaId : Boolean;
      procedure ValidateOption;
      constructor Create(aOwner : TComponent); reintroduce;
      destructor Destroy; override;
  end;
Wenn ich das ganze so aufrufe funktioniert es einwandfrei:

Delphi-Quellcode:
mTest := TPflegestatistikAuswertungOption.Create(blubb);
mTest.OnValidationError := onValidateError;
mTest.ValidateOption;
ich würde das ganze aber gerne wie folgt aufrufen
Delphi-Quellcode:
  for i := 0 to FLoadedOptions.Count - 1 do
  begin
    FLoadedOptions[i].OnValidationError := onValidateError;
    FLoadedOptions[i].ValidateOption;
  end;
FLoaded Options ist die Liste in der sich die Objekte befinden. Kann mir vielleicht irgendjemand sagen, wie ich mein Interface modifizieren muss, damit ich das Event auf Interfaceebene registrieren kann, oder falls dass tatsächlich nicht möglich ist eine Ausweichmöglichkeit nennen, in der ich nicht die Klassen hardcoden muss?

Danke euch schon einmal im Voraus.
Maliko

Uwe Raabe 10. Jan 2022 13:13

AW: Event in Interface vorgeben
 
Prinzipiell könntest du den Event auch im Interface ergänzen, dann aber mit entsprechenden Get und Set Routinen. Das macht aber die simple Implementierung über ein Feld zunichte.

Übergib doch den Event als Parameter an ValidateOption.
Delphi-Quellcode:
  IOptionLogic = interface
    ['{3E8091DE-BE13-4C88-9C2B-F0DF96F78AEE}']
    function GetOption : TPanel;
    function GetOptionType : TOptionType;
    function FirmaId : String;
    function UseOnlyOnFirmaId : Boolean;
    procedure ValidateOption(OnValidationError: TOnValidationError);
  end;
In den Klassen kann dann ja sowas stehen:
Delphi-Quellcode:
      procedure ValidateOption; overload;
      procedure ValidateOption(AOnValidationError: TOnValidationError); overload;

...

TStatistikAuswertungOption.ValidateOption(AOnValidationError: TOnValidationError);
var
  saveEvent: TOnValidationError;
begin
  saveEvent := OnValidationError;
  try
    OnValidationError := AOnValidationError;
    ValidateOption;
  finally
    saveEvent := OnValidationError;
  end;
end;
Sinnvollerweise würde man das in einer virtuellen Basis-Klasse implementieren und das parameterlose ValidateOption jeweils überschreiben.

Maliko 10. Jan 2022 13:19

AW: Event in Interface vorgeben
 
Ja an sowas habe ich tatsächlich auch schon gedacht, aber dann kann ich auch gleich das Controll an die Funktion übergeben, welche vom EventListener mit Inhalt gefüllt wird. Nur wollte ich nach möglichkeit eben genau das nicht. Ich möchte ungerne Form-Übergreifend mit Controlls arbeiten. Darum habe ich halt daran gedacht ein Event zu nutzen, welches einfach den Fehlertext zurück gibt und der Event-Listener füllt dann das Controll, da der Listener sich in der Selben Form wie das Controll befindet.

Edit: Ne moment. Ich hab das Beispiel falsch gelesen. Das ist tatsächlich eine hervorragende Idee, die ich glaube ich auch so umsetze. Danke dir.

himitsu 10. Jan 2022 14:28

AW: Event in Interface vorgeben
 
Oder das ErrorEvent-Property weg
und das Event direkt übergeben

also nur das eine
Delphi-Quellcode:
procedure ValidateOption(OnValidationError: TOnValidationError = nil);
, ohne die Property.

TiGü 10. Jan 2022 15:02

AW: Event in Interface vorgeben
 
Zitat:

Zitat von himitsu (Beitrag 1500386)
Oder das ErrorEvent-Property weg
und das Event direkt übergeben

also nur das eine
Delphi-Quellcode:
procedure ValidateOption(OnValidationError: TOnValidationError = nil);
, ohne die Property.

Wo ist da konkret der Unterschied zu Uwes Vorschlag?

Uwe Raabe 10. Jan 2022 15:15

AW: Event in Interface vorgeben
 
Zitat:

Zitat von TiGü (Beitrag 1500387)
Wo ist da konkret der Unterschied zu Uwes Vorschlag?

Mein letzter Satz
Zitat:

Zitat von Uwe Raabe (Beitrag 1500384)
Sinnvollerweise würde man das in einer virtuellen Basis-Klasse implementieren und das parameterlose ValidateOption jeweils überschreiben.

wäre dann nicht mehr so einfach umsetzbar wie gezeigt.


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