DependencyResolver并从界面获取服务

时间:2017-05-28 17:52:06

标签: c# asp.net-mvc

如果我传递IEvent对象,则DependencyResolver无法解析服务。只有当我传递具体对象时,DependencyResolver才能解析服务。但是我需要传递IEvent对象,所以我可以做什么?

我在这里传递IEvent个对象:

List<IEvent> uncommittedEvents = new List<IEvent> { new NoteCreatedEvent() };

foreach (var @event in uncommittedEvents)
{
    EventBus.Dispatch(@event);
}

我在这里使用DependencyResolver - 它找不到IEvent对象的服务(但是如果我通过NoteCreatedEvent就行了):

public class EventDispatcher
{
    public void Dispatch<TEvent>(TEvent @event) where TEvent : IEvent
    {
        foreach (IEventHandler<TEvent> handler in DependencyResolver.Current.GetServices<IEventHandler<TEvent>>())
        {
            handler.Handle(@event);
        }
    }
}

我的其余代码:

public interface IEventHandler<TEvent> where TEvent : IEvent
{
    void Handle(TEvent @event);
}

public class NoteCreatedEventHandler : IEventHandler<NoteCreatedEvent>
{    
    public void Handle(NoteCreatedEvent @event)
    {
    }        
}

public interface IEvent
{
    Guid AggregateId { get; }
}

public class NoteCreatedEvent : IEvent
{
    public Guid AggregateId { get; set; }
    public string Title { get; set; }
}

// registration:
kernel.Bind<IEventHandler<NoteCreatedEvent>>().To<NoteCreatedEventHandler>().InRequestScope();

1 个答案:

答案 0 :(得分:0)

由于您将事件放在List<IEvent>中,因此会丢失所有编译时类型信息。我讨厌反思,所以如果你能避免将你的事件放在通用列表中,我认为这是最好的,只需直接打电话给你的调度员。

否则,我建议进行以下更改。免责声明,我还没有对此进行过任何测试,因此我可能需要花费一些精力修复我在这里快速输入的内容中的任何错误。首先,通过提供非泛型类型来扩展事件处理程序:

public interface IEventHandler
{
    void Handle(IEvent @event);
}

public interface IEventHandler<TEvent> : IEventHandler where TEvent : IEvent
{
    void Handle(TEvent @event);
}

您的所有处理程序都需要从非泛型接口实现该方法,该接口从您的通用接口调用该版本:

public class NoteCreatedEventHandler : IEventHandler<NoteCreatedEvent>
{
    public void Handle(IEvent @event)
    {
        Handle((NoteCreatedEvent)@event);
    }

    public void Handle(NoteCreatedEvent @event)
    {
    }        
}

然后你的调度员会是这样的:

public class EventDispatcher
{
    public void Dispatch(IEvent @event)
    {
        Type genericHandlerType = typeof(IEventHandler<>);
        Type handlerType = genericHandlerType.MakeGenericType(@event.GetType());

        foreach (IEventHandler handler in DependencyResolver.Current.GetServices(handlerType))
        {
            handler.Handle(@event);
        }
    }
}

如果需要考虑性能,那么您希望将typeof()调用移动到静态,因此每个进程只调用一次,并且可能希望对结果进行缓存MakeGenericType。但话说回来,如果性能是一个问题,那么最好不要重构代码以避免将事件转发给IEvent,这样编译器总能调用正确的Dispatch<TEvent>并避免所有反射。我讨厌反思:)