Внедрение зависимостей (в конструктор) с помощью Quartz (у задания есть конструктор с параметрами), запуск и остановка планировщика с помощью события (щелчок кнопки) в MVC

#c# #asp.net-mvc #asp.net-core #dependency-injection #quartz

Вопрос:

Я попытался внедрить зависимость в свой Кварц. Мне нужно запустить планировщик с помощью моей программы после нажатия кнопки в моем веб-интерфейсе. В общем, у меня было:

 this.job = JobBuilder.Create<Program>()
    .WithIdentity("myJob", "group1")
    .Build();
 

Но это выше просто запускает программу с конструктором по умолчанию (Program()).

К сожалению, у меня есть программа, которой нужен конструктор с параметрами:

 public class Program : IJob, IProgram
    {
        private readonly IDataBaseService _databaseservice;

        public Program(IDataBaseService databaseservice)
        {
            _databaseservice = databaseservice;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            await _databaseservice.DoSmth();
        }
 

Так что мне нужно позвонить Program(IDataBaseService databaseservice)

Я прочитал много руководств, руководств и примеров, но до сих пор не могу найти ответа. Большинство ответов касаются Quartz, начинающегося при запуске приложения, но я хочу, чтобы он начинался с инъекции depndency после того, как я использую кнопку в веб-интерфейсе.

Вот мой код:

Startup.cs:

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IDataBaseService, DB2Service>();
            services.AddTransient<IJobFactory, MyJobFactory>();
            services.AddSingleton<IMyScheduler, MyScheduler>();
            services.AddSingleton<IProgram, Program>();
            services.AddControllersWithViews();
        }
 

Контроллер MVC SiteController.cs:

 public class SiteController : Controller
{
private readonly IMyScheduler _MyScheduler;
private readonly IDataBaseService _DataBaseService;
private readonly IProgram _Program;
    
public SiteController(IMyScheduler MyScheduler, IDataBaseService DataBaseService, IProgram Program)
        {
            _MyScheduler = MyScheduler;
            _DataBaseService = DataBaseService;
            _Program = Program;
        }

//this action is called after button click on web interface
public async Task<ActionResult> ButtonClick()
        { 
            //This is where i want to start Quartz. I don't want it to start at start of app.
            //I want it to start when I click button on web interface.
            await MyScheduler.Run_A_Scheduler();
            return OK();
        }
}
 

MyJobFactory.cs:

 public class MyJobFactory : IJobFactory
    {
        private readonly IServiceProvider _provider;

        public MyJobFactory(IServiceProvider provider)
        {
            _provider = provider;
        }
        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            try
            {
                return (IJob)this._provider.GetService(bundle.JobDetail.JobType);
            }
            catch (Exception e)
            {
                throw new SchedulerException(string.Format("Problem while instantiating job '{0}' from the ASPnet Core IOC", bundle.JobDetail.Key), e);
            }
            
        }

        public void ReturnJob(IJob job)
        {
            var disposable = job as IDisposable;
            disposable?.Dispose();
        }
    }
 

MyScheduler.cs:

 public class MyScheduler: IMyScheduler
{
IScheduler scheduler;
IJobDetail job;
ITrigger trigger;

public MyScheduler(IJobFactory myJobFactory)
    {
       scheduler = new StdSchedulerFactory()
          .GetScheduler()
          .Resu<
       scheduler.JobFactory = myJobFactory;
    }

public async Task Run_A_Scheduler()//this is a function that I am calling from controler
    {
       this.job = CreateJob<Program>() //definition at the end

       this.trigger = TriggerBuilder.Create()
           .StartNow()
           .WithSimpleSchedule(x => x
                .WithIntervalInSeconds(20)  //example with 20 seconds, normaly every other hour
                .RepeatForever())
           .Build();

       await this.scheduler.ScheduleJob(job, this.trigger);
       await this.scheduler.Start(); 
    }
        
private IJobDetail CreateJob<T>() where T : IJob
        {
            return JobBuilder.Create<T>()
                .WithIdentity(typeof(T).Name)
                .Build();
        }
}
 

Program.cs

 public class Program : IJob, IProgram
    {
        private readonly IDataBaseService _databaseservice;

        public Program(IDataBaseService databaseservice)
        {
            _databaseservice = databaseservice;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            await _databaseservice.DoSmth();
        }
 

Interfaces IDataBaseService, IMyScheduler, IProgram are mostly empty and just here for dependency injection sake.
IJobFactory is from Quartz library.

Please help. I tried many solutions, and still I don’t get it. I want to fire with Quartz schedule my Program.cs, which have constructor with parameters. I don’t know, how to invoke Program.cs with quartz schedule when I click button on web interface.