Einzelnen Beitrag anzeigen

Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Den Delegaten nachträglich ändern - Unterschiedliches Verhalten

  Alt 29. Jan 2014, 22:36
Vielen Dank für eure Zeit!

TAggregated/TContainedObject habe ich verstanden, denke ich. Die habe ich schließlich auch erst durch dich kennen gelernt

Aber die versprochene Lösung bringt es nicht: Die Aussage "Interface wird unterstützt ja/nein" wird zwar hier vom Parent abhängig gemacht, aber die resultierende Interface-Referenz zeigt auch hier wieder auf das aggregierte Objekt, nicht den Container.


Ein "Minimalbeispiel" kann man das mit 180 Zeilen schon nicht mehr nennen (als VCL-Formularanwendung). Mit IFDEFs wäre es mMn zu unübersichtlich. In den Anhang lege ich es noch als Projekt.

Vielleicht wäre eine Möglichkeit, eine gleichbleibene Delegaten-Instanz dazwischenzuhängen? Der muss dann halt wiederum das Interface implementieren und es letztendlich an das wirklich gewollte Objekt "dispatchen". Und der kann im Quelltext ja jetzt meinetwegen so hässlich sein wie er will. Die Gedanken werden langsam zu abstrus. Ich bin wohl schon zu lange wach.


Delphi-Quellcode:
unit Unit2;

interface

uses
   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
   System.Classes, Vcl.Graphics,
   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
   IMessageInterface = interface
   ['{F3B8FE2F-C64F-4E5B-B731-6ABB09CDF4E7}']
      procedure ShowMessage();
   end;

   TMessager = class(TAggregatedObject, IMessageInterface)
      private var
        myMessage: String;
      public
        constructor Create(
         const controller: IInterface;
         const myMessage: String
        );
        procedure showMessage();
   end;

   TOtherMessager = class(TAggregatedObject, IMessageInterface)
      procedure showMessage();
    end;

   // deligiert an ein Interface
   TContainerClass = class(TInterfacedObject, IMessageInterface)
      private
        function getMessageDelegate(): IMessageInterface;

      private var
        messageDelegate: IMessageInterface;

      // Delegation: IMessageInterface
      property messageInterface: IMessageInterface
      read getmessageDelegate implements IMessageInterface;

      public
        constructor Create();
        procedure createNewDelegateInstance();
   end;


   // deligiert an eine TMessager-Instanz. Und auf diese Klasse
   // bin ich jetzt festgenagelt
   TOtherContainerClass = class(TInterfacedObject, IMessageInterface)
      private
        function getMessageDelegate(): TMessager;

      private var
        messageDelegate: TMessager;

      // Delegation: IMessageInterface
      property messageInterface: TMessager
      read getmessageDelegate implements IMessageInterface;

      public
        constructor Create();
        procedure createNewDelegateInstance();
   end;



   TMyForm = class(TForm)
      delegateToInterfaceButton: TButton;
      delegateToClassButton: TButton;
      procedure FormCreate(Sender: TObject);
      procedure delegateToInterfaceButtonClick(Sender: TObject);
      procedure delegateToClassButtonClick(Sender: TObject);
   end;

var
   MyForm: TMyForm;

implementation

{$R *.dfm}

procedure TMyForm.delegateToInterfaceButtonClick(Sender: TObject);
var
   container: TContainerClass;
   messageIntf: IMessageInterface;
begin
   container := TContainerClass.Create();
   Supports(container, IMessageInterface, messageIntf);
   messageIntf.ShowMessage(); // Zeigt auf eine TMessager-Instanz

   container.createNewDelegateInstance(); // Jetzt wird an ein TOtherMessager delegiert
   messageIntf.ShowMessage(); // Zeit auf die alte TMessager-Instanz
end;


procedure TMyForm.delegateToClassButtonClick(Sender: TObject);
var
   container: TOtherContainerClass;
   messageIntf: IMessageInterface;
begin
   container := TOtherContainerClass.Create();
   Supports(container, IMessageInterface, messageIntf);
   messageIntf.ShowMessage(); // Zeigt auf eine TMessager-Instanz

   container.createNewDelegateInstance(); // Jetzt wird an ein TOtherMessager delegiert
   messageIntf.ShowMessage(); // Zeit auf eine mittlerweile tote TMessager-Instanz. Erzeugt AV
end;

procedure TMyForm.FormCreate(Sender: TObject);
begin

end;

{ TMessager }



constructor TMessager.Create(
   const controller: IInterface;
   const myMessage: String);
begin
   inherited Create(controller);
   self.myMessage := myMessage;
end;

procedure TMessager.showMessage();
begin
   Vcl.Dialogs.ShowMessage(myMessage);
end;

{ TContainerClass }

constructor TContainerClass.Create();
begin
   inherited Create();
   messageDelegate := TMessager.Create(self, 'Diese TMessager-Instanz wurde im Konstruktor erstellt');
end;

procedure TContainerClass.createNewDelegateInstance();
begin
   messageDelegate := TOtherMessager.Create(self);
end;

function TContainerClass.getMessageDelegate(): IMessageInterface;
begin
   Result := messageDelegate;
end;



{ TOtherMessager }

procedure TOtherMessager.showMessage;
begin
   Vcl.Dialogs.ShowMessage('Ich streike heute');
end;

{ TOtherContainerClass }

constructor TOtherContainerClass.Create();
begin
   inherited Create();
   messageDelegate := TMessager.Create(self, 'Diese TMessager-Instanz wurde im Konstruktor erstellt');
end;

procedure TOtherContainerClass.createNewDelegateInstance();
begin
   messageDelegate.Free();
   messageDelegate :=    TMessager.Create(self, 'Diese Instanz wurde irgendwann später erstellt');
   // Ich kann hier also nur von einer TMessager-Instanz auf eine andere
   // wechseln
end;

function TOtherContainerClass.getMessageDelegate(): TMessager;
begin
   Result := messageDelegate;
end;

end.
Angehängte Dateien
Dateityp: zip Projekt.zip (16,7 KB, 1x aufgerufen)
  Mit Zitat antworten Zitat