使用.NET Core 2.1,我在其中具有以下服务:
public class OrderService : IOrderService
{
public event EventHandler<OrderUpdatedEvent> OrderUpdatedEventHandler;
...
}
我还创建了一个SignalR集线器,如下所示:
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
的构造函数似乎不是在应用程序启动时创建的。
OrderService
已注册为单例:
services.AddSingleton<IOrderService, OrderService>();
我确实在文档中发现.NET仅在“使用”时才会创建单例。我将其理解为“通过HTTP REST调用首次击中与该单例相关的控制器”。
在我的代码中也不是好的,OrderHub
将构造函数DI参数声明为OrderService
而不是IOrderService
。我可以通过将集线器直接注入OrderService
中来解决该问题,但是我想使用事件来在服务之间发生松散耦合,并在发生更改时将内容放到网络套接字上。
答案 0 :(得分:0)
您已经担心,OrderHub
不是在应用程序启动时创建的。当客户端连接或调用集线器上的方法时,将创建集线器。另一个问题是,在客户端已连接或调用了集线器方法之后,集线器将被直接处置。因此,在您的情况下,集线器将立即取消订阅EventHandler。另外,Hub实例不是单例。
当您的主要目标是松散耦合时,我建议以下解决方案:
创建一个IOrderBroadcaster
接口,以便稍后将实现从SignalR更改为另一种技术:
public interface IOrderBroadcaster
{
Task SendUpdate(string order);
}
SignalR版本的实现如下所示:
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);
}
}
还请注意,新广播公司已在Startup.cs
中注册了DI:
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);
}
}
通过这种解决方案,您已经实现了宽松的耦合,并且不需要EventHandlers,在我看来,应尽可能避免使用该事件处理程序。
编码愉快!