Dependency injection 在TopShelf和Quartz示波器问题中使用Microsoft DependencyInjection
我使用TopShelf和Quartz作为Windows服务来安排一些作业。对于依赖项注入,我使用Microsoft.Extensions.DependencyInjection包。我的问题是关于范围功能,我希望在范围生命周期中配置服务(例如ISampleService)时,在每轮运行的作业中,处置范围生命周期服务,并在下一轮中再次实例化,但范围生命周期的行为类似于单例生命周期。以下是我的代码: 依赖项:Dependency injection 在TopShelf和Quartz示波器问题中使用Microsoft DependencyInjection,dependency-injection,windows-services,quartz-scheduler,topshelf,Dependency Injection,Windows Services,Quartz Scheduler,Topshelf,我使用TopShelf和Quartz作为Windows服务来安排一些作业。对于依赖项注入,我使用Microsoft.Extensions.DependencyInjection包。我的问题是关于范围功能,我希望在范围生命周期中配置服务(例如ISampleService)时,在每轮运行的作业中,处置范围生命周期服务,并在下一轮中再次实例化,但范围生命周期的行为类似于单例生命周期。以下是我的代码: 依赖项: using Microsoft.Extensions.DependencyInjection
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Topshelf;
主要方法:
static void Main(string[] args)
{
var provider = RegisterServices();
HostFactory.Run(cfg =>
{
cfg.Service<SampleTask>(s =>
{
s.ConstructUsing(() => provider.GetService<SampleTask>());
s.WhenStarted(async f => await f.Start(provider));
s.WhenStopped(f => f.Stop());
});
cfg.RunAsLocalSystem();
cfg.SetDescription("description");
cfg.SetDisplayName("name");
cfg.SetServiceName("service");
});
}
任务:
我创建了一个WorkerService项目,并在
csproj
文件中添加了一些必需的包,如下所示
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.9" />
<PackageReference Include="Topshelf" Version="4.2.1" />
<PackageReference Include="Topshelf.Extensions.Hosting" Version="0.4.0" />
<PackageReference Include="Quartz" Version="3.2.2" />
</ItemGroup>
</Project>
通过更改
Service1
类的依赖范围,您可以看到所有的依赖级别都得到了支持。我创建了一个WorkerService项目,并在csproj
文件中添加了一些必需的包,如下所示
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.9" />
<PackageReference Include="Topshelf" Version="4.2.1" />
<PackageReference Include="Topshelf.Extensions.Hosting" Version="0.4.0" />
<PackageReference Include="Quartz" Version="3.2.2" />
</ItemGroup>
</Project>
通过更改
Service1
类的依赖范围,您可以看到所有的依赖级别都得到了支持。您解决过这个问题吗?@DaImTo是的,我添加了我的解决方案tomorrow@MohammadAkbari很多时间过去了,但也许你仍然可以发布解决方案?@MohammadAkbari你的解决方案是什么?@HeikoScholze我已经添加了我的解决方案你解决过这个问题吗?@DaImTo是的,我添加了我的解决方案tomorrow@MohammadAkbari很多时间过去了,但也许你仍然可以发布解决方案?@MohammadAkbari你的解决方案是什么?@HeikoScholze我已经添加了我的解决方案
public class SampleTask
{
private readonly ISchedulerFactory _schedulerFactory;
public SampleTask(ISchedulerFactory schedulerFactory)
{
_schedulerFactory = schedulerFactory;
}
public async Task Start(ServiceProvider provider)
{
var scheduler = await _schedulerFactory.GetScheduler();
scheduler.JobFactory = new JobFactory(provider);
var job = JobBuilder.Create<IJob>().Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("Sample1", "SampleGroup")
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(10)
.RepeatForever())
.StartNow()
.Build();
await scheduler.ScheduleJob(job, trigger);
await scheduler.Start();
}
public bool Stop()
{
return true;
}
}
public class SampleJob : IJob
{
private readonly ISampleService _sampleService;
public SampleJob(ISampleService sampleService)
{
_sampleService = sampleService;
}
public async Task Execute(IJobExecutionContext context)
{
await Task.FromResult(0);
}
}
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.9" />
<PackageReference Include="Topshelf" Version="4.2.1" />
<PackageReference Include="Topshelf.Extensions.Hosting" Version="0.4.0" />
<PackageReference Include="Quartz" Version="3.2.2" />
</ItemGroup>
</Project>
public class JobFactory : IJobFactory
{
private readonly IServiceProvider _serviceProvider;
public JobFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return _serviceProvider.GetRequiredService<QuartzJobRunner>();
}
public void ReturnJob(IJob job)
{
// we let the DI container handler this
}
}
[DisallowConcurrentExecution]
public class QuartzJobRunner : IJob
{
private readonly IServiceProvider _serviceProvider;
public QuartzJobRunner(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Execute(IJobExecutionContext context)
{
using (var scope = _serviceProvider.CreateScope())
{
if (scope.ServiceProvider
.GetRequiredService(context.JobDetail.JobType) is IJob job)
await job.Execute(context);
}
}
}
public class QuartzHostedService : BackgroundService
{
private readonly ISchedulerFactory _schedulerFactory;
private readonly IJobFactory _jobFactory;
public QuartzHostedService(ISchedulerFactory schedulerFactory,
IJobFactory jobFactory)
{
_schedulerFactory = schedulerFactory;
_jobFactory = jobFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var scheduler = await _schedulerFactory.GetScheduler(stoppingToken);
scheduler.JobFactory = _jobFactory;
var jobDetail = JobBuilder
.Create<Job1>()
.WithIdentity("Job1")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("Trigger1")
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(15)
.RepeatForever())
.StartNow()
.Build();
await scheduler.ScheduleJob(jobDetail, trigger, stoppingToken);
await scheduler.Start(stoppingToken);
}
}
[DisallowConcurrentExecution]
public class Job1 : IJob
{
private readonly ILogger<Job1> _logger;
private readonly Service1 _service1;
public Job1(ILogger<Job1> logger, Service1 service1)
{
_logger = logger;
_service1 = service1;
}
public Task Execute(IJobExecutionContext context)
{
_logger.LogInformation($"Service Id: {_service1.Id}");
return Task.CompletedTask;
}
}
public class Service1
{
public string Id { get; set; }
public Service1()
{
Id = Guid.NewGuid().ToString();
}
}
public class Program
{
public static void Main(string[] args)
{
var hostBuilder = CreateHostBuilder(args);
if (Debugger.IsAttached)
{
hostBuilder.Build().Run();
}
else
{
hostBuilder.RunAsTopshelfService(hc =>
{
hc.SetDisplayName("Task1");
hc.SetDescription("Task1");
hc.SetServiceName("Task1");
});
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<IJobFactory, JobFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
services.AddSingleton<QuartzJobRunner>();
services.AddScoped<Job1>();
services.AddSingleton<Service1>();
//services.AddScoped<Service1>();
//services.AddTransient<Service1>();
services.AddHostedService<QuartzHostedService>();
});
}
services.AddSingleton<IJobFactory, JobFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
services.AddSingleton<QuartzJobRunner>();
services.AddScoped<Job1>();