Интерфейсный метод как обработчик событий - PullRequest
4 голосов
/ 06 августа 2010

Возможно ли использовать интерфейсный метод в качестве обработчиков событий в Delphi 2007? Простые версии не работают:

type
  TMyEvent = procedure of object;

  IMyInterface = interface
    procedure Handler;
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)
  public
    procedure Handler;
  end;

var
  ev: TMyEvent;
  obj: TMyClass;
  intf: IMyInterface;
begin
  obj := TMyClass.Create;
  intf := obj;
  ev := obj.Handler; // compiles
  ev := intf.Handler; // <== Error E2010 (incompatible types)
end.

Добавление @ или Addr изменяет ошибку на E2036 (требуется переменная).

Обновление: Это

procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer);
type
  TVtable = array[0..999] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  //QI=0, AddRef=1, Release=2, etc
  TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo];
  TMethod(MethPtr).Data := Pointer(IntRef);
end;

var
  ev: TMyEvent;
  intf: IMyInterface;
begin
  intf := TMyClass.Create;
  IntRefToMethPtr(intf, ev, 3);
  ev;
end.

работает. Однако я не слишком люблю там магию 3.

1 Ответ

2 голосов
/ 06 августа 2010

Более чистое решение - реализовать IInterfaceComponentReference или нечто подобное для вашего базового класса и использовать его для получения класса ref.

Приведенный выше код не будет работать, например, FPC и другие совместимые. Их структура VMT немного отличается. И даже в Delphi это может привести к будущему расширению языка.

Идеальным решением было бы иметь для этого совершенно отдельный тип метода "interface", но мне интересно, стоит ли это того.

...