从 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 无法知道如何绑定 ICallback
和IJob
。想怎么约束他们?
最简单的解决方案是在这两个 类
之间引入依赖关系
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>());
因此始终为每个单独的作业执行正确的回调。
我有不同的 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 无法知道如何绑定 ICallback
和IJob
。想怎么约束他们?
最简单的解决方案是在这两个 类
之间引入依赖关系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>());
因此始终为每个单独的作业执行正确的回调。