代码之家  ›  专栏  ›  技术社区  ›  Wim Deblauwe

如何将EventHandler与带有.NET核心的信号器集线器相结合?

  •  0
  • Wim Deblauwe  · 技术社区  · 7 年前

    使用.NET Core 2.1,我有这样的服务:

    public class OrderService : IOrderService
    {
        public event EventHandler<OrderUpdatedEvent> OrderUpdatedEventHandler; 
    
        ...
    }
    

    public class OrderHub : Hub
    {
        private OrderService _orderService;
        private EventHandler<OrderUpdatedEvent> _eventHandler;
    
        public OrderHub(OrderService orderService)
        {
            Console.WriteLine("OrderHub created...");
            _orderService = orderService;
            _eventHandler = (sender, updateEvent) => { SendUpdateOverWebsocket(updateEvent); };
            _orderService.OrderEventHandler += _eventHandler;
            Console.WriteLine("Event handler added!");
        }
    
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            _orderService.OrderUpdatedEventHandler -= _eventHandler;
        }
    

    OrderService 我有这样一句话:

    OrderUpdatedEventHandler?.Invoke(this, new OrderUpdatedEvent(orderId, ...));
    

    OrderUpdatedEventHandler 总是 null 因为 OrderHub

    这个 订单服务

    services.AddSingleton<IOrderService, OrderService>();
    

    我确实在文档中发现.NET只会在“使用”时创建单例实例。我把它理解为“第一次通过一个HTTP调用命中了一个REST控制器”。

    将构造函数DI参数声明为 订单服务 IOrderService . 我可能可以通过直接将集线器注入 订单服务

    1 回复  |  直到 7 年前
        1
  •  2
  •   Daniel Beckmann    7 年前

    OrderHub 不是在应用程序启动时创建的。当客户机连接或调用集线器上的方法时,将创建集线器。另一个问题是,在客户端连接或调用Hub方法之后,Hub将被直接释放。因此,在您的情况下,中心将立即取消订阅EventHandler。此外,Hub实例不是单例实例。

    创建 IOrderBroadcaster 接口,以便以后将实现从信号器更改为另一种技术:

    public interface IOrderBroadcaster
    {
        Task SendUpdate(string order);
    }
    

    Signaler版本的实现如下所示:

    public class WebSocketOrderBroadcaster : IOrderBroadcaster
    {
        private IHubContext<OrderHub> orderHubContext;
    
        public WebSocketOrderBroadcaster(IHubContext<OrderHub> orderHubContext)
        {
            this.orderHubContext = orderHubContext;
        }
    
        public Task SendUpdate(string order)
        {
            return this.orderHubContext.Clients.All.SendAsync("Update", order);
        }
    }
    

    还要注意,新的广播公司已经注册了DI-in Startup.cs

    services.AddSingleton<IOrderBroadcaster, WebSocketOrderBroadcaster>();
    

    对于这个解决方案 Hub 可以保持空:

    public class OrderHub : Hub
    {
    }
    

    在你的 OrderService 然后,可以注入IOrderBroadcaster并调用更新方法:

    public class OrderService : IOrderService
    {
        private IOrderBroadcaster broadcaster;
    
        public OrderService(IOrderBroadcaster broadcaster)
        {
            this.broadcaster = broadcaster;
        }
    
        public void UpdateOrder(string order)
        {
            this.broadcaster.SendUpdate(order);
        }
    }
    

    通过这个解决方案,您实现了松耦合,并且不需要eventhandler,在我看来,如果可能的话,应该避免使用eventhandler。

    编码快乐!