In Delphi is it possible to bind an interface to an object that doesn't implement it

前端 未结 2 681
自闭症患者
自闭症患者 2021-02-14 08:01

I know Delphi XE2 has the new TVirtualInterface for creating implementations of an interface at runtime. Unfortunately I am not using XE2 and I\'m wondering what kind of hackery

2条回答
  •  鱼传尺愫
    2021-02-14 08:33

    I'm not sure, what you want to accomplish and why you want to dynamically bind that interface, but here is a way to do it (don't know if it fits your need):

    type
      IMyInterface = interface
      ['{8A827997-0058-4756-B02D-8DCDD32B7607}']
        procedure Go;
      end;
    
      TMyClass = class(TInterfacedObject, IInterface)
      private
        FEnabled: Boolean;
      protected
        property Enabled: Boolean read FEnabled;
      public
        constructor Create(AEnabled: Boolean);
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        procedure Go; //I want to dynamically bind IMyInterface.Go here
      end;
    
      TMyInterfaceWrapper = class(TAggregatedObject, IMyInterface)
      private
        FMyClass: TMyClass;
      protected
        property MyClass: TMyClass read FMyClass implements IMyInterface;
      public
        constructor Create(AMyClass: TMyClass);
      end;
    
    constructor TMyInterfaceWrapper.Create(AMyClass: TMyClass);
    begin
      inherited Create(AMyClass);
      FMyClass := AMyClass;
    end;
    
    constructor TMyClass.Create(AEnabled: Boolean);
    begin
      inherited Create;
      FEnabled := AEnabled;
    end;
    
    procedure TMyClass.Go;
    begin
      ShowMessage('Go');
    end;
    
    function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult;
    begin
      if Enabled and (IID = IMyInterface) then begin
        IMyInterface(obj) := TMyInterfaceWrapper.Create(Self);
        result := 0;
      end
      else begin
        if GetInterface(IID, Obj) then
          Result := 0
        else
          Result := E_NOINTERFACE;
      end;
    end;
    

    And this is the corresponding test code:

    var
      intf: IInterface;
      my: IMyInterface;
    begin
      intf := TMyClass.Create(false);
      if Supports(intf, IMyInterface, my) then
        ShowMessage('wrong');
    
      intf := TMyClass.Create(true);
      if Supports(intf, IMyInterface, my) then
        my.Go;
    end;
    

提交回复
热议问题