delphidwscript

Using / injecting an interface instance implemented in Delphi in dwscript


I have an interface (in fact multiple interfaces) which I'd like to use this way:

Is there any possibility to do so?

I tried to provide methods returning those interfaces in a class, but when I used this class over RTTI those methods where not found.


Solution

  • As I stated above it isn't immediately possible to declare an interface and implement it Delphi side with a TdwsUnit. It is however possible to achieve what you're after in other ways.

    I'm assuming that you have declared both your interface and your class in a TdwsUnit. Let's call them IMyInterface and TMyClass.

    type
      IMyInterface = interface
        procedure SetValue(const Value: string);
        function GetValue: string;
        property Value: string read GetValue write SetValue;
        procedure DoSomething;
      end;
    
    type
      TMyClass = class(TObject)
      protected
        procedure SetValue(const Value: string);
        function GetValue: string;
      public
        property Value: string read GetValue write SetValue;
        procedure DoSomething;
      end;
    

    Solution 1 - Alter the class declaration at run time

    Create an event handler for the TdwsUnit.OnAfterInitUnitTable event and add the interface to the class declaration:

    procedure TDataModuleMyStuff.dwsUnitMyStuffAfterInitUnitTable(Sender: TObject);
    var
      ClassSymbol: TClassSymbol;
      InterfaceSymbol: TInterfaceSymbol;
      MissingMethod: TMethodSymbol;
    begin
      // Add IMyInterface to TMyClass
      ClassSymbol := (dwsUnitProgress.Table.FindTypeLocal('TMyClass') as TClassSymbol);
      InterfaceSymbol := (dwsUnitProgress.Table.FindTypeLocal('IMyInterface') as TInterfaceSymbol);
      ClassSymbol.AddInterface(InterfaceSymbol, cvProtected, MissingMethod);
    end;
    

    Now you can access an instance of the class though an interface in your script:

    var MyStuff: IMyInterface;
    MyStuff := TMyObject.Create;
    MyStuff.DoSomething;
    

    Solution 2 - Use duck typing

    Since DWScript supports duck typing you don't actually need to declare that your class implements an interface. Instead you just state what interface you need and let the compiler figure out if the object can satisfy that need:

    var MyStuff: IMyInterface;
    MyStuff := TMyObject.Create as IMyInterface;
    MyStuff.DoSomething;