Delphi 如何使用params调用TEvent的简单示例

Delphi 如何使用params调用TEvent的简单示例,delphi,spring4d,Delphi,Spring4d,我试图使用Spring4d框架进行Delphi,我想使用多播事件。在使用“普通”TNotifyEvent时,它可以工作,并且处理程序将被调用两次 uses ... Spring, Spring.Events, Spring.Events.Base; procedure TfrmMain.EventHandler1(Sender: TObject); begin Log('called handler1'); end; procedure TfrmMain.btnNotif

我试图使用Spring4d框架进行Delphi,我想使用多播事件。在使用“普通”TNotifyEvent时,它可以工作,并且处理程序将被调用两次

uses
  ...
  Spring,
  Spring.Events,
  Spring.Events.Base;

procedure TfrmMain.EventHandler1(Sender: TObject);
begin
  Log('called handler1');
end;

procedure TfrmMain.btnNotifyEventClick(Sender: TObject);
var
  MulticastEvent: TEvent<TNotifyEvent>;
begin
  MulticastEvent := TEvent<TNotifyEvent>.Create;
  try
    MulticastEvent.Add(EventHandler1);
    MulticastEvent.Add(EventHandler1);
    MulticastEvent.Add(EventHandler1);
    MulticastEvent.Remove(EventHandler1);
    MulticastEvent.Invoke;
  finally
    MulticastEvent.Free;
  end;
end;
此代码编译时不会出现错误消息“方法调用的参数太多”。不幸的是,在框架或项目页面上没有使用多播事件的示例。我使用的是Delphi10.3.3社区版


谢谢。

您不应该使用
Spring.Events.pas
中的
TEvent
类,因为它是一个实现细节,事实上,在2.0中,它甚至不再存在,因为它被重构了。
相反,请使用
Spring.pas
中的记录类型
Event
。它不需要创建或销毁,因为它是自动创建或销毁的

在代码中更改后,您将看到缺少
Sender
参数。
按Ctrl+Shift+Space查看
Invoke
的参数-它与您提供的
T
类型的签名完全相同

固定代码:

procedure TfrmMain.btnSyncEventClick(Sender: TObject);
var
  MulticastEvent: Event<TSyncEvent>;
begin
  MulticastEvent.Add(EventHandler2);
  MulticastEvent.Add(EventHandler2);
  MulticastEvent.Invoke(Sender, 'text for handler2');
end;
过程TfrmMain.btnSyncEventClick(发送方:TObject);
变量
多播事件:事件;
开始
MulticastEvent.Add(EventHandler2);
MulticastEvent.Add(EventHandler2);
调用(发送方,'text for handler2');
结束;

我不使用Spring4D,因此我无法具体回答这个问题,但您想要的应该可以通过标准的Delphi轻松实现。错误消息表明无法传递要调用的参数,因此需要从支持该参数的
TEvent
类派生一个类。如果您有
TEvent
类的源代码,那么您应该能够轻松地对其进行扩展,以复制
Invoke
函数,从而允许它接受一个参数并传递它。您可能会发现,将其编写为从泛型继承的标准类比将其保持为泛型更容易。谢谢Rob。这是完全正确的。但我的希望是,正如斯特凡指出的那样,这个框架有一个更好的方法
procedure TfrmMain.btnSyncEventClick(Sender: TObject);
var
  MulticastEvent: Event<TSyncEvent>;
begin
  MulticastEvent.Add(EventHandler2);
  MulticastEvent.Add(EventHandler2);
  MulticastEvent.Invoke(Sender, 'text for handler2');
end;