1

我有一个标准的 ASP.NET MVC 3 Web 应用程序。

我有几个横切关注点,我希望使用一些 AOP,最值得注意的是事件分派器模式。

例如,当发生某些事情时,我希望在我的控制器中“引发一个事件”,然后在我的应用程序(存储库、服务等)中散布几个“监听器”,它们监听这个事件并采取相应的行动。

我还应该提到,我将 StructureMap 用于我的 IoC 容器 - 所以最好是事件调度程序为 IoC 容器使用(或可插入),而不是依赖它自己的容器。

有没有人找到一个可以执行此操作的 NuGet 包,或者可以将我指向一篇文章/问题,说明如何执行此操作?

4

2 回答 2

4

控制器应该是无状态的。框架在处理请求后销毁控制器对象,并在下一个请求到来时重新创建它。实际上 ASP.NET MVC 为每个请求创建单独的控制器实例。在控制器中声明事件并由其他应用程序服务订阅此事件可能会导致内存泄漏(GC 不会破坏已使用的控制器,因为会有来自其他活动对象的活动引用控制器)。

还要记住,如果IIS空闲或由于其他原因,IIS 可能会终止您的 Web 应用程序的进程,因此您的Web 应用程序也应该是 stateless

您还必须记住该事件处理的并发性,

您可以使用事件发布者-订阅者模式,但它应该被实现为单独的“代理”,例如 Windows 服务,它将侦听某些端口并处理来自您的 Web 应用程序的请求。

于 2012-09-03T06:45:30.007 回答
0

我认为您的控制器不应该引发事件,在您完成特定域的验证后,这应该是您的域逻辑的东西。在您完成验证以确保它会起作用之前,您如何确定某些事情确实发生了?

然而,实现一个简单的基于事件的解决方案并不难。我会选择类似的东西:

public abstract class BaseEvent {}

public class EventRouter {
            private Dictionary<Type, List<Action<BaseEvent>>> _eventRoutes;

    public EventRouter ()
    {
        _eventRoutes= new Dictionary<Type, List<Action<BaseEvent >>>();
    }

    public void Register<TEvent>(Action<TEvent> route) where TEvent : BaseEvent
    {
        List<Action<TEvent>> routes;
        var type = typeof(BaseEvent);
        if (_eventRoutes.TryGetValue(type, out routes).IsFalse())
        {
            routes = new List<Action<TEvent>>();
            _eventRoutes.Add(type, routes);
        }
        routes.Add((y) => route(y as BaseEvent));
    }

    public bool TryGetValue(Type commandType, out List<Action<TEvent>> handlers)
    {
        return _eventRoutes.TryGetValue(eventType, out handlers);
    }
}

public class InMemoryEventDispatcher : IEventBus
{
    private readonly IEventRouter _eventRouter;

    public InMemoryEventBus(IEventRouter eventRouter)
    {
        _eventRouter = eventRouter;
    }

    public void PublishEvent<TEvent>(TEvent @event) where TEvent : BaseEvent
    {
        var eventType = @event.GetType();
        List<Action<TEvent>> eventHandlers;
        if (_eventRouter.TryGetValue(eventType, out eventHandlers).IsTrue())
        {
            foreach (var eventHandler in eventHandlers)
            {
                eventHandler(@event);
            }
        }
    }

    public void PublishEvents<TEvent>(IEnumerable<BaseEvent> events) where TEvent : BaseEvent
    {
        foreach (var @event in events)
        {
            PublishEvent(@event);
        }
    }
}

准备就绪后,您可以注册每个事件要执行的操作。我还没有编译它,但应该有类似的东西。

于 2012-09-03T07:02:16.520 回答