提问人:Vikneshwaran Seetharaman 提问时间:9/23/2023 最后编辑:Vikneshwaran Seetharaman 更新时间:9/23/2023 访问量:46
无法解析 c# .NET Core 的 Webapp 程序 .cs 中的实例
Unable to resolve the instance in Webapp program.cs in c# .NET Core
问:
我有 4 个 c# 项目
WebApp
(ASP.NET 核心 MVC Web 应用程序)EmailNotificationService
(类库)PushNotificationService
(类库)EventBroker
(类库)
在 Web 应用程序中,我运行了一个后台服务,它持续侦听队列(作为单例注入)。队列由 Web 应用更新,后台服务从队列中读取并处理每个项目,然后将其上传到数据库。后台服务还包含一个实例(注入到单例中),它使用该实例发布上载事件EventManager
public class UploadBackgroundService : BackgroundService
{
private readonly UploadQueue _workerQueue;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<UploadQueue> _logger;
private readonly EventManager _eventManager;
public UploadBackgroundService (UploadQueue workerQueue, IServiceProvider serviceProvider, ILogger<UploadQueue > logger, EventManager eventManager)
{
_workerQueue = workerQueue ?? throw new ArgumentNullException(nameof(workerQueue));
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
_eventManager = eventManager ?? throw new ArgumentNullException(nameof(eventManager));
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
using IServiceScope scope = _serviceProvider.CreateScope();
using DbContext dbContext = scope.ServiceProvider.GetService<DbContext >() ?? throw new Exception("Database context is null!");
await foreach(Func<DbContext , Task<Models.UploadResult>> workItem in this._workerQueue.ReadAsyncStream())
{
UploadResult uploadResult = await workItem(dbContext);
_eventManager.NotifyObservers(new UploadResult(Enums.UploadStatus.Error));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
该项目包含一个类,该类创建上传事件并通知其所有订阅者。EventBroker
EventManager
public class EventManager
{
public event EventHandler<UploadEventArgs>? UploadEvent;
public virtual void OnUpload(UploadEventArgs uploadEventArgs)
{
UploadEvent?.Invoke(this, uploadEventArgs);
}
public void NotifyObservers(object uploadResult)
{
UploadEventArgs uploadEventArgs = new UploadEventArgs();
uploadEventArgs.Data = JsonConvert.SerializeObject(uploadResult);
OnUpload(uploadEventArgs);
}
}
包含一个电子邮件使用者类,该类订阅 EventManager 中的上传事件,并在收到通知时向用户发送电子邮件。EmailNotificationsService
public class EmailConsumer : IConsumer
{
private readonly IEmailSender _emailSender;
public EmailConsumer(IEmailSender emailSender)
{
_emailSender = emailSender ?? throw new ArgumentNullException(nameof(emailSender));
}
public void Subscribe(EventManager eventBroker)
{
eventBroker.UploadEvent += SendEmailNotifications!;
}
public void SendEmailNotifications(object sender, UploadEventArgs eventArgs)
{
EmailUploadResult uploadResult = JsonConvert.DeserializeObject<EmailUploadResult>(eventArgs.Data) ?? throw new InvalidDataException("Corrupt data");
_emailSender.SendEmailAsync(null, new List<Address> { new Address("testcapsdev@outlook.com") }, null, null, null, uploadResult);
}
}
包含 signalRNotification 使用者类,该类订阅 EventManager 中的上传事件,并在收到通知时向 UI 发送推送通知。PushNotificationsService
public class SignalRNotificationConsumer: IConsumer
{
private readonly IHubContext<NotificationHub, INotificationHub> _hubContext;
public SignalRNotificationConsumer(IHubContext<NotificationHub, INotificationHub> hubContext)
{
_hubContext = hubContext;
}
public void Subscribe(EventManager eventBroker)
{
eventBroker.UploadEvent += SendSignalRNotifications!;
}
private void SendSignalRNotifications(object sender, UploadEventArgs uploadEventArgs)
{
try
{
SignalRUploadResult uploadResult = JsonConvert.DeserializeObject<SignalRUploadResult >(uploadEventArgs.Data) ?? throw new InvalidDataException("Corrupt data");
_hubContext.Clients.All.UploadNotifications(uploadResult);
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
现在我正在订阅网络应用程序内的事件:program.cs
var services = builder.Services;
services.AddSingleton<UploadQueue, UploadQueue>();
services.AddSingleton<EventManager, EventManager>();
services.AddScoped<SignalRNotificationConsumer>().AddScoped<IConsumer, SignalRNotificationConsumer>(s => s.GetService<SignalRNotificationConsumer>()!);
services.AddScoped<EmailConsumer>().AddScoped<IConsumer, EmailConsumer>(s => s.GetService<EmailConsumer>()!);
services.AddScoped<IEmailSender, EmailSender>();
var app = builder.Build();
EventManager eventBroker = app.ServiceProvider.GetService<EventManager>()!;
IConsumer consumer = (IConsumer)app.ServiceProvider.GetService(typeof(EmailConsumer))!;
consumer.Subscribe(eventBroker);
IConsumer consumer = (IConsumer)app.ServiceProvider.GetService(typeof(SignalRNotificationConsumer))!;
consumer.Subscribe(eventBroker);
现在我收到一个错误
无法解析来自根提供程序的作用域服务
我不想在后台服务中订阅,该服务工作正常。因为后台服务不必知道有关订阅者的任何信息。
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
IConsumer signalRConsumer = (IConsumer)_serviceProvider.CreateScope().ServiceProvider.GetService(typeof(SignalRNotificationConsumer))! ?? throw new ArgumentNullException("SignalRConsumer");
IConsumer emailConsumer = (IConsumer)_serviceProvider.CreateScope().ServiceProvider.GetService(typeof(EmailConsumer))! ?? throw new ArgumentNullException("SignalRConsumer");
signalRConsumer.Subscribe(_eventManager);
emailConsumer.Subscribe(_eventManager);
while (!stoppingToken.IsCancellationRequested)
{
try
{
using IServiceScope scope = _serviceProvider.CreateScope();
using DbContext dbContext = scope.ServiceProvider.GetService<DbContext >() ?? throw new Exception("Database context is null!");
await foreach(Func<DbContext , Task<Models.UploadResult>> workItem in this._workerQueue.ReadAsyncStream())
{
UploadResult uploadResult = await workItem(dbContext);
_eventManager.NotifyObservers(new UploadResult(Enums.UploadStatus.Error));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
上面的代码工作正常。
所以有人可以指出正确的方向。我的想法合适吗?以及如何在不让后台服务初始化订阅者的情况下完成这项工作。
答: 暂无答案
上一个:在进程外运行时处理命令失败
评论