Использование/внедрение экземпляра интерфейса, реализованного в Delphi, в dwscript

У меня есть интерфейс (на самом деле несколько интерфейсов), который я хотел бы использовать следующим образом:

  • Сделайте блоки, в которых объявлены интерфейсы, доступными внутри сценария dwscript (если необходимо).

  • Создайте объекты, реализующие интерфейсы, в хост-приложении, написанном на Delphi.

  • Сделайте эти интерфейсы каким-то образом доступными для сценария dwscript.

  • И используйте их как обычно внутри скрипта.

Есть ли возможность сделать это?

Я пытался предоставить методы, возвращающие эти интерфейсы в классе, но когда я использовал этот класс поверх RTTI, эти методы не были найдены.


person Sebastian Jänicke    schedule 13.09.2015    source источник
comment
Насколько мне известно, на данный момент это невозможно. Интерфейсы могут быть объявлены в TdwsUnit, но реализовать интерфейсы на стороне Delphi невозможно. См. также: dwsUnit: функция, возвращающая интерфейс   -  person SpeedFreak    schedule 13.09.2015
comment
На самом деле это возможно. Просто не так, как можно было бы ожидать. Дайте мне секунду, чтобы ввести ответ...   -  person SpeedFreak    schedule 13.09.2015


Ответы (1)


Как я уже говорил выше, невозможно сразу объявить интерфейс и реализовать его на стороне Delphi с помощью TdwsUnit. Однако можно добиться того, что вам нужно, другими способами.

Я предполагаю, что вы объявили свой интерфейс и свой класс в файле TdwsUnit. Назовем их IMyInterface и 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;

Решение 1. Измените объявление класса во время выполнения.

Создайте обработчик события TdwsUnit.OnAfterInitUnitTable и добавьте интерфейс в объявление класса:

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;

Теперь вы можете получить доступ к экземпляру класса через интерфейс в вашем скрипте:

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

Решение 2. Используйте утиную печать

Поскольку DWScript поддерживает утиный ввод, вам фактически не нужно объявлять, что ваш класс реализует интерфейс. Вместо этого вы просто указываете, какой интерфейс вам нужен, и позволяете компилятору выяснить, может ли объект удовлетворить эту потребность:

var MyStuff: IMyInterface;
MyStuff := TMyObject.Create as IMyInterface;
MyStuff.DoSomething;
person SpeedFreak    schedule 13.09.2015
comment
Спасибо. Это работает, но я нахожу это довольно сложным. На данный момент мы рассматриваем альтернативы, например, paxCompiler. Он поддерживает интерфейсы напрямую и поддерживает мобильные платформы. - person Sebastian Jänicke; 03.10.2015