从 quartz 作业回调到 class

callback to class from quartz job

我有不同的 classes 作为基数 class(工人)的后代。 这些 classes 中的每一个都有自己的石英作业和触发器以及 回调。

public class Worker1 : Worker, ICallback
{
    IScheduler scheduler;
    public Worker1(IScheduler scheduler)
        : base("Worker1")
    {
        this.scheduler = scheduler;
        IJobDetail job = JobBuilder.Create<MonitorJob>()
            .WithIdentity(name + "Job")
            .Build();
        ITrigger trigger = TriggerBuilder.Create()
            .WithIdentity(name + "Trigger")
            .StartNow()
            .WithSimpleSchedule(x => x
                .WithIntervalInSeconds(1)
                .RepeatForever())
            .Build();
        scheduler.ScheduleJob(job, trigger);
    }

    public void Callback()
    {
        Console.WriteLine(name + " callback " + DateTime.Now.ToLongTimeString());
    }
}

现在我想要触发 job1(从 worker1)到 worker1.callback 的回调。 与 job2 相同(来自 worker2)回调 worker2.callback.

使用 autofac,我可以将回调注入到我的工作中 - 但是我只能注入一个通用回调,而不是像我喜欢的那样为每个 class.

public class MonitorJob : IJob
{
    ICallback callback;

    public MonitorJob(ICallback callback)
    {
        this.callback = callback;
    }

    public void Execute(IJobExecutionContext context)
    {
        callback.Callback();
    }
}

my main class 创建 autofac 容器

 container = ConfigureContainer(new ContainerBuilder()).Build();
 using (container.BeginLifetimeScope())
 {
      workers.Add(container.Resolve<Worker1>());
      workers.Add(container.Resolve<Worker2>());
 }
 var factory = container.Resolve<ISchedulerFactory>();
 var scheduler = factory.GetScheduler();
 scheduler.Start();

 internal static ContainerBuilder ConfigureContainer(ContainerBuilder cb)
 {
      cb.RegisterModule(new QuartzAutofacFactoryModule());
      cb.RegisterModule(new QuartzAutofacJobsModule(typeof(QuartzScheduler.MonitorJob).Assembly));
      cb.RegisterType<Worker1>().AsSelf();
      cb.RegisterType<Worker2>().AsSelf();
      return cb;
  }

Autofac 创建作业,也可以通过回调注入它,但是我希望工作人员 class 的正确回调 "owns" 作业。

这怎么可能?

否则我需要以某种方式从一个公共回调传播到相应的工作人员class。

提前致谢

Autofac 无法知道如何绑定 ICallbackIJob。想怎么约束他们?

最简单的解决方案是在这两个 类

之间引入依赖关系
public class MonitorJob : IJob
{
    public MonitorJob(Worker1 worker1)
    {
        this._worker1 = worker1;
    }

    private readonly Worker1 _worker1;

    public void Execute(IJobExecutionContext context)
    {
        this._worker1.Callback();
    }
}

如果不可能,您可以使用 Keyed service :

public class MonitorJob : IJob
{
    public MonitorJob([WithKey("Worker1")]ICallback callback)
    {
        this._callback = callback;
    }

    private readonly ICallback _callback;

    public void Execute(IJobExecutionContext context)
    {
        this._callback.Callback();
    }
}

你必须这样注册cb.RegisterType<Worker1>().Keyed<ICallback>("Worker1")

如果这样修改你的代码还是不行,你可以新建一个模块来添加参数:

public class CallbackModule : Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        if (registration.Services.OfType<TypedService>()
                                 .Any(s => s.ServiceType == typeof(IJob)))
        {
            registration.Preparing += (sender, e) =>
            {
                // bind ICallback and IJob here
                if (registration.Activator.LimitType == typeof(Job1))
                {
                    e.Parameters = e.Parameters
                                    .Concat(new TypedParameter[] { TypedParameter.From<ICallback>(e.Context.Resolve<Worker1>()) });
                }
            };
        }
    }
}

并且可以这样注册:

    ContainerBuilder cb = new ContainerBuilder();
    cb.RegisterModule(new CallbackModule());
    cb.RegisterType<Worker1>().As<ICallback>().AsSelf();
    cb.RegisterType<Worker2>().As<ICallback>().AsSelf();
    IContainer container = cb.Build();

顺便说一句,下面的代码包含一个错误:

using (container.BeginLifetimeScope())
{
  workers.Add(container.Resolve<Worker1>());
  workers.Add(container.Resolve<Worker2>());
}

您创建了一个新的 ILifetimeScope 但没有使用它。应改用以下代码:

using (ILifetimeScope scope = container.BeginLifetimeScope())
{
  workers.Add(scope.Resolve<Worker1>());
  workers.Add(scope.Resolve<Worker2>());
}

如果想在调用execute方法时得到通知,可以实现一个JobListener for this. You can create one listener for all jobs or multiple listeners, one per job type perhaps, and then apply the appropriate matcher. Here's a link that might be useful with more details on job listeners and listeners in general: Quartz.Net Job Listeners, Part 3 of Quartz.net Listeners in detail

我成功创建了一个通用作业:

public class MonitorJob<T> : IJob where T:IWorker
{
    T worker;

    public MonitorJob(T worker)
    {
        this.worker = worker;
    }

    public void Execute(IJobExecutionContext context)
    {
        worker.Callback();
    }
}

在我的自定义工作器中 class 我为这个工作器创建了监视器作业:

public Worker1(IScheduler scheduler)
{
   this.scheduler = scheduler;

   IJobDetail job = JobBuilder.Create<MonitorJob<Worker1>>()
      .WithIdentity(name + "Job")
      .Build();
        [...]
 }

因此正确的回调 class 将通过以下方式解决:

container.RegisterType<Worker1>().AsSelf().SingleInstance();
container.RegisterType<MonitorJob<Worker1>>().AsSelf();

[...]
workers.Add(scope.Resolve<Worker1>());

因此始终为每个单独的作业执行正确的回调。