【问题标题】:Event Dispatching in .NET.NET 中的事件调度
【发布时间】:2012-09-03 06:24:13
【问题描述】:

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

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

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

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

有没有人找到可以做到这一点的 NuGet 包,或者,可以向我指出一篇文章/问题,说明如何做到这一点?

【问题讨论】:

    标签: .net aop event-dispatching


    【解决方案1】:

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

    另外请记住,如果 IIS 可能会终止您的 Web 应用程序的进程,如果它处于空闲状态或由于某些其他原因,因此您的 Web 应用程序也应该是无状态的 .

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

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

    【讨论】:

      【解决方案2】:

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

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

      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);
              }
          }
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-11
        • 2021-01-08
        • 2011-08-24
        • 2017-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-13
        相关资源
        最近更新 更多