使用Quartz调度作业时出现依赖注入生命周期冲突错误
Quartz作业调度启动报错:单例服务无法消费作用域服务
在项目中使用Quartz进行作业调度时,启动阶段抛出System.AggregateException,提示部分服务无法构造。核心原因是:单例生命周期的SendReminderEmails服务尝试消费作用域生命周期的Clinical.Infrastructure.Emails.IAppointmentEmailSender服务,导致服务描述符验证失败。
相关代码
Program.cs
using CcAcca.ApplicationInsights.ProblemDetails; using Clinical; using Clinical.Application; using Clinical.Application.Sockets; using Clinical.Domain.TemplateAggregate; using Clinical.Infrastructure.Scheduling.Reminders.Services; using Clinical.Infrastructure.Scheduling.Reminders; using H1.Clinical.Api; using Hellang.Middleware.ProblemDetails; using Kernel; using Kernel.Messaging; using Kernel.Mongo; using Kernel.Web; using Kernel.Web.Authentication; using MassTransit; using MassTransit.SignalR; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.FeatureManagement; using Microsoft.OpenApi.Models; using Quartz.Impl; using Quartz.Spi; using Quartz; using Serilog; var builder = WebApplication.CreateBuilder(args); builder.Configuration.AddEnvironmentVariables(); var jwtSettings = new JwtBearerSettings(); builder.Configuration.Bind(nameof(JwtBearerSettings), jwtSettings); try { Log.Logger = new LoggerConfiguration() .CreateBootstrapLogger(); builder.Host.UseSerilog((hostingContext, service, loggerConfiguration) => loggerConfiguration .WriteTo.ApplicationInsights(service.GetRequiredService<TelemetryConfiguration>(), TelemetryConverter.Traces) .WriteTo.Console() .Filter.ByExcluding(e => e.Exception is TaskCanceledException) .ReadFrom.Configuration(hostingContext.Configuration)); Log.Information("healthONE Clinical应用启动中"); builder.Services.AddSignalR(o => { o.HandshakeTimeout = TimeSpan.FromSeconds(5); o.KeepAliveInterval = TimeSpan.FromSeconds(30); }); var section = builder.Configuration.GetSection(nameof(MemorySettings)); builder.Services.Configure<MemorySettings>(section); var memorySettings = new MemorySettings(); section.Bind(memorySettings); builder.Services .AddHealthChecks() .AddProcessAllocatedMemoryHealthCheck(memorySettings.MaxMemoryInMb); builder.Services.AddControllers(); builder.Services.AddFeatureManagement(); builder.Services .AddApplicationInsightsTelemetry(options => { options.EnablePerformanceCounterCollectionModule = false; }) .AddProblemDetailTelemetryInitializer() .AddEndpointsApiExplorer() .AddJwtAuthentication(jwtSettings); builder.Services.AddSwaggerGen((Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions c) => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "healthONE Clinical API", Version = "v1", Description = "模块化临床API" }); c.EnableAnnotations(); c.UseAllOfForInheritance(); c.SelectSubTypesUsing(baseType => { if (baseType == typeof(ITemplateField)) { return new List<Type>() { typeof(MultiLineText), typeof(Canvas), typeof(Dropdown), typeof(RadioButtonGroup), typeof(SingleLineText), typeof(CheckboxGroup), typeof(TimePicker), typeof(DatePicker) }; } return Enumerable.Empty<Type>(); }); }); builder.Services .RegisterKernelDependencies() .RegisterWebKernel(builder.Environment) .RegisterMongoKernel(builder.Configuration, schemaCreatorLocation: null) .RegisterClinical(builder.Configuration) .RegisterMessaging( builder.Configuration, options => { options.AddSignalRHub<DiaryHub>(); options.AddSignalRHub<ConsultationHub>(); options.AddSignalRHub<ArchiveHub>(); options.AddConsumersFromNamespaceContaining(typeof(ClinicalApplicationModule)); }); builder.Services.AddHostedService<QuartzHostedService>(); builder.Services.AddSingleton<IJobFactory, SingletonJobFactory>(); builder.Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>(); builder.Services.AddSingleton<SendReminderEmails>(); builder.Services.AddSingleton(new EmailSenderJob(type: typeof(SendReminderEmails), expression: "0/30 0/1 * 1/1 * ? *")); } catch (Exception ex) { Log.Fatal(ex, "启动过程中发生未处理异常"); throw; } finally { Log.Debug("关闭完成"); Log.CloseAndFlush(); } var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(); app.UseProblemDetails(); if (app.Environment.IsDevelopment()) { app.UseSerilogRequestLogging(); } app.UseAuthentication(); app.MapHealthChecks("/healthz"); app.UseAuthorization(); app.MapControllers(); app.MapHub<DiaryHub>("hubs/clinical/diary"); app.MapHub<ConsultationHub>("hubs/clinical/consultation"); app.MapHub<ArchiveHub>("hubs/clinical/archive"); app.Run();
SendReminderEmails.cs
using Quartz; using Kernel.Users; using Clinical.Infrastructure.Emails; using Clinical.Domain.ReminderAggregate; using Clinical.Infrastructure.Emails.Models; namespace Clinical.Infrastructure.Scheduling.Reminders.Services { public class SendReminderEmails : IJob { private readonly IReminderRepository _reminderRepository; private readonly IAppointmentEmailSender _appointmentEmailSender; public SendReminderEmails(IReminderRepository reminderRepository, IAppointmentEmailSender appointmentEmailSender) { _reminderRepository = reminderRepository; _appointmentEmailSender = appointmentEmailSender; } public async Task Execute(IJobExecutionContext context) { var reminders = await _reminderRepository.GetAllRemindersofToday(); foreach (var reminder in reminders) { //var email = reminder.Email; var recipientEmailAddress = Email.TryMake("aliwaheed51@gmail.com"/*patientBooking.Email*/); //if (recipientEmailAddress is null) // return BadRequest($"'{patientBooking.Email}' 不是有效的{nameof(Email)}"); var recipients = new RecipientsModel { primaryRecipientEmail = recipientEmailAddress }; await _appointmentEmailSender.SendEmail(recipients, "Ali Waheed" /*当前用户全名*/, "已预约"); }; } } }
错误信息
System.AggregateException HResult=0x80131500 消息=部分服务无法构造(验证服务描述符时出错 '服务类型: Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails 生命周期: Singleton 实现类型: Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails': 无法从单例 'Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails' 中使用作用域服务 'Clinical.Infrastructure.Emails.IAppointmentEmailSender'。) 来源=Microsoft.Extensions.DependencyInjection 调用栈: 在 Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options) 在 Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) 在 Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder) 在 Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder) 在 Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider() 在 Microsoft.Extensions.Hosting.HostBuilder.Build() 在 Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build() 在 Program.<Main>$(String[] args) 位置 E:\Altron\Altron-Backend\src\H1\Clinical.Api\Program.cs:第133行 此异常最初引发于以下调用栈: [外部代码] 内部异常1: InvalidOperationException: 验证服务描述符时出错 '服务类型: Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails 生命周期: Singleton 实现类型: Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails': 无法从单例 'Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails' 中使用作用域服务 'Clinical.Infrastructure.Emails.IAppointmentEmailSender'。 内部异常2: InvalidOperationException: 无法从单例 'Clinical.Infrastructure.Scheduling.Reminders.Services.SendReminderEmails' 中使用作用域服务 'Clinical.Infrastructure.Emails.IAppointmentEmailSender'。
内容的提问来源于stack exchange,提问作者Ali Waheed
相关产品推荐
相关产品推荐

