Delphi中匿名方法动态绑定事件

应恢弘之约,写了一个对其发布的匿名函数动态绑定到事件的封装,代码如下:

type
  TAnonEvent=class
  public
    class function Wrap<T1,T2>(OnEvent:T1):T2;
    class procedure Remove<TEventType>(const AEvent: TEventType);
  end;
{ TAnonEvent }

class procedure TAnonEvent.Remove<TEventType>(const AEvent: TEventType);
var
  AMethod:TMethod absolute AEvent;
begin
  if Assigned(AMethod.Data) then
    IInterface(AMethod.Data)._Release;
end;
class function TAnonEvent.Wrap<T1,T2>(OnEvent: T1):T2;
var
  Addr:Pointer;
  AMethod:PMethod;
begin
Addr:=PPointer(@OnEvent)^;
AMethod:=@Result;
AMethod.Code:=PPointer(IntPtr(PPointer(Addr)^)+SizeOf(Pointer)*3)^;//QueryInterface/AddRef/Release/Invoke
AMethod.Data:=Pointer(Addr);
end;
 
type
  TNotifyEventA=reference to procedure(ASender:TObject);
procedure TForm3.Button1Click(Sender: TObject);
begin
Button2.OnClick:=TAnonEvent.Wrap<TNotifyEventA,TNotifyEvent>(procedure (sender: tObject)
     begin
      Button2.Caption:=DateTimeToStr(Now);
       ShowMessage('OK');
      TAnonEvent.Remove<TNotifyEvent>(Button2.OnClick);
      Button2.OnClick:=nil;
     end);
Button2.OnClick(Sender);
end;

【注意】

由于匿名函数中,我将TMethod.Data指向了匿名函数对应的接口对象,所以在匿名函数中,不要使用Self来代表当前对象。如果非要使用的话,那么自己修改下Wrap的代码,将AMethod.Data:=Pointer(Addr)改为指向当前函数所隶属对象的Self即可。

分享到: