请考虑以下代码:
public interface IEventHandler<in T> where T : IEvent
{
void Execute(T @event);
}
对于这些处理程序,我实现了一些具体的处理程序子类:
public class SomeEventHandler : IEventHandler<SomeEvent>
{
public void Execute(SomeEvent @event) { /* ... */ }
}
现在我有一个工厂来检索事件的相应处理程序:
public class EventHandlerFactory : IEventHandlerFactory
{
public IEventHandler<T> Create<T>(T @event) where T : IEvent
{
// What to do in here?
}
}
我试图检查事件的类型然后返回相应的处理程序,但当然类型系统否认:
if(@event is SomeEvent)
{
return (IEventHandler<T>) new SomeEventHandler();
}
我不会这么做,但我想知道如何允许代码使Create<T>
的接口成为可能。
编辑:当我遍历一大堆事件时,T被视为IEvent,因此类型系统将抛出异常:
var events = IEnumarable<IEvent>() { /* ... */ };
foreach (var @event in events)
{
var eventHandler = eventHandlerFactory.Create(@event);
}
Create(T @event)
- 方法将引发异常,因为T是IEvent而不是具体类型。我可以使用(dynamic) @event
来解决它,但这不是我真正想做的事情。
答案 0 :(得分:1)
经典工厂模式。
我喜欢做的事情如下:
public class EventHandlerFactory : IEventHandlerFactory
{
private readonly Dictionary<Type, Type> _eventHandlers = new Dictionary<Type, Type>();
public EventHandlerFactory()
{
//add a mapping between the type, and the handler
//note - this could be done with reflection to automate this
_eventHandlers.Add(typeof(SomeEvent), typeof(SomeEventHandler));
}
public IEventHandler<T> Create<T>(T @event) where T : IEvent
{
var handler = _eventHandlers[typeof(T)];
if (handler != null)
{
//now use Activator.CreateInstance to instantiate the type
return (IEventHandler<T>)Activator.CreateInstance(handler);
}
throw new Exception("Handler not found");
}
}
答案 1 :(得分:0)
替代解决方案:
如果您想避免反射,或者您的IEventHandler实现没有默认构造函数:
public interface IEventHandler
{
}
public interface IEventHandler<in T> : IEventHandler where T : IEvent
{
void Execute(T @event);
}
public class EventHandlerFactory
{
private static readonly Dictionary<Type, Func<IEventHandler>> _eventHandlers = new Dictionary<Type, Func<IEventHandler>>
{
{ typeof(SomeEvent), () => new SomeEventHandler() }
};
public IEventHandler<T> Create<T>(T @event) where T : IEvent
{
Func<IEventHandler> handler;
if (_eventHandlers.TryGetValue(typeof(T), out handler))
{
return (IEventHandler<T>)handler();
}
throw new Exception("Handler not found");
}
}