Hello,
I am using Lazarus for a school project and I'm trying to make an EventManager class for it.
I want the Event Listeners to be able to register custom callbacks, so they can do this for example:
constructor TSomething.Create(game: TGame);
begin
game.eventmanager.listen(@self.onPlayerDeath, TPlayerDeathEvent);
end;
procedure TSomething.onPlayerDeath(e: TPlayerDeathEvent);
begin
// do something
end;
normally you'd do something like this in the eventmanager class:
type
TEventClass = class of TEvent;
TEventCallback = procedure(e: TEvent) of object;
TEventManager = class
private
eventclasses: array of TEventClass;
eventcallbacks: array of array of TEventCallback;
// etc
end;
When you want to fire an Event, you'd just find the index of an event class and then call all callbacks that are in eventcallbacks[index of the event class].
However, I want the callback procedures to take the specialized Event as an Argument, as you can see in my first code example.
(onPlayerDeath takes TPlayerDeathEvent as an Argument, NOT TEvent!; that is a difference from the definition of TEventCallback)
The first problem, which is a minor one, is that the compiler would probably error when I'd assign @InstanceOfTSomething.onPlayerDeath to let's say eventcallbacks[0][0]; because the arguments of the procedures aren't of the same type. My solution would be let the type TEventCallback equal TMethod, then there'd be no checks. But how do I call a TMethod when I the argument type varies?
What is the best way to achieve this?
Some ideas:
- somehow using generics
- using assembly to call the callbacks
- just disposing the whole concept and using TEvent as an argument type for all callbacks