我正在尝试实现诸如EventBus之类的东西,我的类是:
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
}
}
以及预期的用法:
var eventBus = new EventBus();
eventBus.Register(new SomeEventHandler());
eventBus.Handle(new SomeEvent("some data"));
显然,EventBus无法正常工作,因为在调用Handle之前,我必须存储类型或强制转换事件/事件处理程序
有任何线索吗?
谢谢!
答案 0 :(得分:2)
您遇到的问题是此行key
if (keyArray[i].Key.Equal(key)) //Use ".Equals()" instead of "=="
{
keyArray[i] = new KeyValueGeneric<T>(key, value);
matchFound = true;
}
是类型var eventType = event_.GetType();
,其中不包含名为var
的方法
所以您要做的是像{p1一样将Type
的{{1}}更改为
Handle
答案 1 :(得分:1)
在可能相当迅速地发送事件的环境中使用dynamic
可能会涉及过多的开销。
代替查找处理程序对象,而是查找处理程序委托。
进一步的解释在下面的代码中。
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);
}
}