Reputation: 7492
I'm trying to implement something like an EventBus, my classes are:
public interface IEventHandler<in T>
{
void Handle(T event_);
}
public class SomeEventHandler: IEventHandler<SomeEvent>
{
public void Handle(SomeEvent event_)
{
Console.WriteLine(event_.SomeData);
}
}
public class SomeEvent
{
private readonly string _someData;
public string SomeData { get => _someData; }
public SomeEvent(string someData)
{
_someData = someData;
}
}
public class EventBus
{
private readonly Dictionary<Type, object> _handlers = new Dictionary<Type, object>(); // probably the object should be something like IEventHandler<?>
public void Register<T>(IEventHandler<T> eventHandler)
{
_handlers[typeof(T)] = eventHandler;
}
public void Handle(object event_) // I want to keep this Handle interface as (object event_) (without any <T>)
{
var eventType = event_.GetType();
var eventHandler = _handlers[eventType];
eventHandler.Handle(event_); // this will not work
}
}
And the expected usage:
var eventBus = new EventBus();
eventBus.Register(new SomeEventHandler());
eventBus.Handle(new SomeEvent("some data"));
Obviously the EventBus isn't working because I have to store the type or cast the event / event handler before calling the Handle
Any clue?
Thanks!
Upvotes: 0
Views: 94
Reputation: 4947
Using dynamic
in an environment where you could be pumping events fairly rapidly will likely involve too much overhead.
Instead of keeping a lookup of handler objects, keep a lookup of handler delegates.
Further explanation is within the code that follows.
public class EventBus
{
// Change the type of values to Action<object>
private readonly Dictionary<Type, Action<object>> _handlers = new Dictionary<Type, Action<object>>();
public void Register<T>(IEventHandler<T> eventHandler)
{
// When you store the lookup, create the handler.
_handlers[typeof(T)] = CreateHandler(eventHandler);
}
private Action<object> CreateHandler<T>(IEventHandler<T> eventHandler)
{
// The lambda that's created here is an Action<object> and the cast assumes that
// someData is of the correct type.
return someData => eventHandler.Handle((T)someData);
}
public void Handle(object @event)
{
var eventType = @event.GetType();
var eventHandler = _handlers[eventType];
// The dictionary gives back an Action<object> that you can call directly.
eventHandler(@event);
}
}
Upvotes: 1
Reputation: 1816
the problem you have is that this line var eventType = event_.GetType();
var
is the type Type
which does not contains a method called Handle
so what you have to do is change the public void Handle(object event_)
for dynamic
like
public void Handle(dynamic event_)
{
var eventType = event_.GetType();
var eventHandler = _handlers[eventType];
eventHandler.Handle(event_); // this will work
}
fiddle https://dotnetfiddle.net/UrnCv5
Upvotes: 2