我有不同的类作为基类(Worker)的后代。 这些类中的每一个都有它自己的石英作业和触发器和a 回调。
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我能够将回调注入我的工作 - 但是我只能注入一个共同的回调,而不是我喜欢每个类的回调。
public class MonitorJob : IJob
{
ICallback callback;
public MonitorJob(ICallback callback)
{
this.callback = callback;
}
public void Execute(IJobExecutionContext context)
{
callback.Callback();
}
}
我的主类创建了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会创建作业,也可以通过回调注入它,但是我希望从“拥有”作业的工人类中获得正确的回调。
这怎么可能?
否则我需要以某种方式从一个公共回调传播到相应的工人类。
提前谢谢
答案 0 :(得分:0)
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>());
}
答案 1 :(得分:0)
如果您希望在调用execute方法时收到通知,则可以为此实现JobListener。您可以为所有作业或多个侦听器创建一个侦听器,可能为每个作业类型创建一个侦听器,然后应用适当的匹配器。这里有一个链接,可能对工作听众和听众的更多细节有用:Quartz.Net Job Listeners, Part 3 of Quartz.net Listeners in detail
答案 2 :(得分:0)
我成功创建了一个通用的工作:
public class MonitorJob<T> : IJob where T:IWorker
{
T worker;
public MonitorJob(T worker)
{
this.worker = worker;
}
public void Execute(IJobExecutionContext context)
{
worker.Callback();
}
}
在我的自定义工作者类中,我为该worker创建了监视器作业:
public Worker1(IScheduler scheduler)
{
this.scheduler = scheduler;
IJobDetail job = JobBuilder.Create<MonitorJob<Worker1>>()
.WithIdentity(name + "Job")
.Build();
[...]
}
所以正确的回调类将通过以下方式解决:
container.RegisterType<Worker1>().AsSelf().SingleInstance();
container.RegisterType<MonitorJob<Worker1>>().AsSelf();
[...]
workers.Add(scope.Resolve<Worker1>());
所以总是为每个单独的工作执行正确的回调。