c# - 在哪里实例化处理 .NET Core 中的服务事件的类?
问题描述
我遇到的问题是关于设计和结构方法,当在 ASP.NET Core 中需要处理服务事件时,我应该在哪里实例化一个这样做的类/接口?例如,我可以为 MyClass 注册一个作用域,该作用域将通过构造函数注入 MyService ,但然后又将这个 MyClass 放在哪里?
我创建了一个服务并将其注册为单例范围,该服务正在运行。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlServer()
.AddDbContext<Senseflow.Database.SolutionModuleContext>(opts => opts.UseSqlServer
(Configuration.GetConnectionString("Database")));
services.Configure<MQTTConfig>(Configuration.GetSection("MQTT"))
.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, MQTTService>();
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
var container = ContainerConfig.Build();
container.Populate(services);
AppContainer = container.Build();
return new AutofacServiceProvider(AppContainer);
}
现在,您可以看到 MQTTService 已注册并正在运行。我应该采取什么方法来注册可以处理由 MQTTService 触发的“EventX”的 MyClass?以及在哪里实例化/注入它?
解决方案
你的是一个网络应用程序。通常,类是为了响应 Web 请求而实例化的。当应用程序收到请求时,它会创建一个控制器,然后如果其他类被注入到控制器中,它会创建这些类,依此类推。
这使得它不清楚如何响应来自MQTTService
适合的事件,因为您的控制器正在响应 Web 请求,而不是来自MQTTService
.
如果应用程序的目的只是响应来自MQTTService
. 您可以在 Web 应用程序中执行相同的操作:
首先,定义响应事件的类,注入MQTTService
其中并分配事件处理程序。顺便说一句,我假设您正在使用此页面上的代码:
public class MqttServiceEventListener // first name that popped into my head
{
private readonly MQTTService _mqttService;
public MqttServiceEventListener(MQTTService mqttService)
{
_mqttService = mqttService;
// add event handlers
}
}
在ConfigureServices
. 这是因为您可能希望将处理事件所需的其他依赖项注入到此类中。只要所有内容都注册了,IServiceCollection
您就可以从容器中解析整个类。
接下来,您将需要一个MqttServiceEventListener
. 它可以由静态类或 t 拥有,但如果它不会被实例化以响应 Web 请求,那么另一个解决方案就是在启动时创建一个实例并让它监听事件。有几种方法可以做到这一点,并且偏好会有所不同。
你可以这样做:
public static class MqttServiceEventListenerExtensions
{
private static MqttServiceEventListener _eventListener;
public static void UseMqttServiceEventListener(this IApplicationBuilder app)
{
if (_eventListener == null) return; //or throw an InvalidOperationException
_eventListener = app.ApplicationServices.GetService<MqttServiceEventListener>();
}
}
现在,在 中Startup.Configure
,调用它:
app.UseMqttServiceEventListener();
对此有一个很大的警告是,我不知道您的事件侦听器的生命周期需要是什么,或者它的依赖项的生命周期需要是什么。使用像这样的单个实例可能就是您所需要的,或者它可能会导致问题。
如果注册为单例的类在您的场景中不好:
一个类似的选项可能是跳过事件侦听器的静态实例,只注册一个处理事件的类(或者甚至是不同的类来处理不同的事件),如下所示:
public class MqttServiceEventHandler
{
public void MqttServerClientConnected(object sender, MqttClientConnectedEventArgs e)
{
// handle the event
}
}
IServiceProvider
同样的事情 - 向容器注册事件处理程序。如果它们需要更短的生命周期,您可以将它们设为瞬态。
现在,在您的扩展类中,改为执行以下操作:
public static class MqttServiceEventListenerExtensions
{
private static MQTTService _mqttService; // likely unnecessary
public static void UseMqttServiceEventListener(this IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
// This is registered as a singleton, so there's only going to be on instance.
_mqttService = serviceProvider.GetService<MQTTService>();
// Add event handlers that resolve the needed class and pass the
// event to it.
_mqttService.ClientDisconnected += (sender, eventArgs) =>
{
var handler = serviceProvider.GetService<MqttServiceEventHandler>();
handler.MqttServerClientConnected(sender, eventArgs);
};
}
}
同样的事情Startup.Configure
:app.UseMqttServiceEventListener();
首先,您要解析MQTTService
,将其注册为单例,因此服务提供者将始终返回相同的实例。是否需要在类中实际存储对它的引用是有争议的。您始终可以删除_mqttService
,将其解析MQTTService
为局部变量,并向其中添加事件处理程序。
接下来,您将添加事件处理程序来解析处理事件所需的类,然后将事件参数传递给它。同样,这需要预先注册所有这些类。但这很好,因为这意味着您可以在需要时将更多依赖项注入这些类,依此类推。
如果一个类太大,它还使您可以灵活地创建不同的类来处理不同的事件。扩展方法可以解析一个类来处理一个事件,另一个类来处理另一个事件,等等。并且生命周期不是问题,因为事件处理程序类在您需要它们之前不会被解析。根据您的需要,它们可以是临时的或单例的。
推荐阅读
- postgresql - 将文件内容复制到 PVC 中的 Postgres 表中
- google-chrome-extension - 使用 chrome.storage,如何将字符串保存到本地存储中,然后测试是否存在?
- django - Django中的NoReverseMatch错误,无法传递id参数
- android - 如果我的视图寻呼机中有回收站视图,如何使活动可以垂直滚动?
- node.js - SyntaxHighlighter 的 npm 构建问题
- html - 如何使用 rgba(0,0,0,0.5) 使我的背景变暗
- ios - 使用页面视图控制器在视图之间滑动时防止视图控制器更新
- jquery - 将 c# 数据表绑定(传递)到 jquery 数据表导致错误
- python - 一种删除列表中仅一个元素的连续重复项的pythonic方法
- go - Golang 反射:检查结构类型定义以在不初始化的情况下提取其属性