仅通过接口注入信号机集线器



所以最近我开始了一个以Ardalis Clean Architecture为模板的项目,这一切都很好,但当signalR进入我的项目时,我无法理解它。我试图注入我的集线器实现的接口并调用它的方法,但每次调用它时都会抛出NullReferenceException,在这个注入的接口中,似乎所有的signalR组件都为空。使用AutoFac注册所有集线器并注册其接口。当我被迫在核心层中引用signalR包时,尽量避免出现这种情况。

核心层:

public class UpdateTimerNotificationHandler : INotificationHandler<UpdateTimerNotification>
{
private readonly ITimerHub _timerHub;
public UpdateTimerNotificationHandler(ITimerHub timerHub)
{
_timerHub = timerHub;
}
public Task Handle(UpdateTimerNotification notification, CancellationToken cancellationToken)
{
return _timerHub.UpdateTimerAsync(notification);
}
}
public interface ITimerHub
{
Task UpdateTimerAsync(UpdateTimerNotification updateTimerNotification);
}

基础设施层:

public class TimerHub : Microsoft.AspNetCore.SignalR.Hub, ITimerHub
{
private readonly IAccountRepository _accountRepository;
public TimerHub(IAccountRepository accountRepository)
{
_accountRepository = accountRepository;
}
public Task UpdateTimerAsync(UpdateTimerNotification updateTimerNotification)
{
return Clients.All.SendAsync("UpdateTimer", updateTimerNotification);
}
}
private void RegisterHubs(ContainerBuilder builder)
{
foreach (var assembly in _assemblies)
{
builder.RegisterHubs(assembly);
}
builder.RegisterType<TimerHub>().As<ITimerHub>();
}

Web层:

builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterModule(new DefaultCoreModule());
containerBuilder.RegisterModule(
new DefaultInfrastructureModule(builder.Environment.EnvironmentName == "Development"));
});
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
var app = builder.Build();
GlobalHost.DependencyResolver = new AutofacDependencyResolver(app.Services.GetAutofacRoot());

我尝试手动注册集线器,但运气不好,仍然是问题

好消息是SignalR已经实现了IHubContext<T>。在您的情况下,您不需要注入ITimerHub接口。如果你的TimerHub已经实现了ITimerHub,那就足够好了。在你的情况下,它看起来像这个

public class HomeController : Controller
{
private readonly IHubContext<TimerHub> _hubContext;
public HomeController(IHubContext<TimerHub> hubContext)
{
_hubContext = hubContext;
}
}

你也没有展示你的startup.cs类。

public void ConfigureServices(IServiceCollection services)
{
...
services.AddSignalR();
...
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.MapHub<TimerHub>("/yourEndPointGoesHere");
}

如果你真的想,我不建议你[在这里看][1]有一个在泛型代码中使用IHubContext的示例。

我知道你在努力学习新东西。是的,解耦应用程序非常重要,这样您就可以朝着正确的方向前进。但是,我不建议您采用这种方法。他的方法不适用于99%的项目。让我解释一下我的观点。不要被他视频和博客中的热门话题所吸引。重要的是要理解这些主体是你的应用程序的主体。

  1. 您的应用程序中没有15000个类、服务、视图和N层等。

  2. 您不需要域驱动方法的灵活性。我见过大规模的,我指的是大规模的项目,那些有25年历史、有数百万行代码的项目。让我告诉你,你不会像他所说的那样随意地交换你的数据层;它使它变得容易";这样做的方法。把它放在回购协议和数据访问层中并没有真正的帮助。您可以将其放入数据访问层或服务中。您仍然需要测试150000行代码。它唯一对我有用的一次是当我有4个数据源时,它们都有一个getBy...函数,需要聚合来自4个源的信息。单元测试也不需要它。只需在单元测试中创建一个mock变量,无需模拟数据库连接。我发现让单元测试真正连接到数据库更有用,即使它是一个依赖项,但它实际上很有用。

  3. 他自己说";你可以使用一个极简主义的API,并从那里开始工作;这就是你应该做的。在一个没有代码的项目中,SOLID和Repos有什么意义?例如,实体中的I是接口的实现。接口做两件事-

A。告诉你的应用程序它应该做什么,不应该做什么。那么,你在执行什么,这可能会破坏或需要这种抽象?

B。解除应用程序的耦合。根据类型,在一段具有相同DoSomething()的代码中注入了3+个不同的类,这在哪里?

他谈到了只有当你有500件不同的事情发生时才适用的其他事情,而在他的情况下,这仍然是夸大其词。

如果你想打破它,你可以采取一个简单的方法。

-MainApiProject
-ServicesProject (you can also put interfaces in here)
-InterfacesProject(if you need them between multiple projects and have a lot of them)
-UtilitiesProject

然后看看他在做什么,如果你看到你需要,就接受它。我可以继续,但这段时间越来越长了。[1] :https://learn.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-6.0

这就是我使用的方法(集线器和接口(:

private readonly IHubContext<MessageHub,IMsgHub> HubContext;
public BMController(IHubContext<MessageHub, IMsgHub> ctx)
{
HubContext = ctx;
}

最新更新