应恢弘之约,写了一个对其发布的匿名函数动态绑定到事件的封装,代码如下:
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即可。