delphispring4d

Simple example how to Invoke TEvent with params


I'm trying to use the Spring4d framework for Delphi and I want to use the Multicast Events. While using the "normal" TNotifyEvent, it works and the handler will get called twice.

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;

But I can't figure out how to use these Multicast events with my own Event TSyncEvent. The EventHandler2 expects a string. So I want to call the Invoke-method with the text.

type
  TSyncEvent = procedure(Sender: TObject; const iMsg: string) of object;

procedure TfrmMain.EventHandler2(Sender: TObject; const iMsg: string);
begin
  Log('called handler2: '+iMsg);
end;

procedure TfrmMain.btnSyncEventClick(Sender: TObject);
var
  MulticastEvent: TEvent<TSyncEvent>;
begin
  MulticastEvent := TEvent<TSyncEvent>.Create;
  try
    MulticastEvent.Add(EventHandler2);
    MulticastEvent.Add(EventHandler2);
    MulticastEvent.Invoke('text for handler2');
  finally
    MulticastEvent.Free;
  end;
end;

This code does not compile with the error message "too many params for method Invoke". Unfortunately there is no example using the Multicast events in the framework or on the project page. I'm using Delphi 10.3.3 Community Edition.

Thank you.


Solution

  • You are not supposed to use the TEvent<T> class from Spring.Events.pas because it's an implementation detail and in fact, in 2.0 it will not even exist anymore because it was refactored.
    Instead, use the record type Event<T> from Spring.pas. It does not need to be created nor destroyed because it does that automatically.

    Once you change that in your code you will see that you are missing the Sender argument.
    Press Ctrl+Shift+Space to see the parameters of Invoke - it has exactly the same signature of the type of T you are providing.

    Fixed code:

    procedure TfrmMain.btnSyncEventClick(Sender: TObject);
    var
      MulticastEvent: Event<TSyncEvent>;
    begin
      MulticastEvent.Add(EventHandler2);
      MulticastEvent.Add(EventHandler2);
      MulticastEvent.Invoke(Sender, 'text for handler2');
    end;