花了超過半天的時間歸結了數個類別之後,才找到問題,簡化來看,跑不起來的長的像
public class MyJob1 : IJob
{
public string Input { get; set; }
public MyJob1(string input)
{
Input = input;
}
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("【" + Input + "】" + context.Trigger.Key.Name);
}
}
而可以跑起來的則是
public class MyJob2 : IJob
{
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("【MyJob2】" + context.Trigger.Key.Name);
}
}
這樣就比較明顯了,差別就是建構子,石英自己去建 Job 的時候需要一個空白參數的建構子,沒有的話根本連 Job 都沒建,沒跑,Listener 當然也不會有錯誤訊息,如果加個
public class MyJob1 : IJob
{
public string Input { get; set; }
public MyJob1()
{
Input = "MyJob1";
}
public MyJob1(string input)
{
Input = input;
}
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("【" + Input + "】" + context.Trigger.Key.Name);
}
}
就可以跑起來可,問題是我實際上需要跑起來的是有傳入 input 的那個,而且專案裡東西都是用 Autofac 建的,只有這邊改做法顯然不對。 查了一下 Quartz 要定義 Job 的建構過程細節要自己去實作 IJobFactory 然後再指派給 IScheduler。
sealed class AutofacJobFactory : IJobFactory
{
IContainer _container;
public AutofacJobFactory(IContainer inj)
{
_container = inj;
}
/// <summary>Core, build IJob instance</summary>
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
// use bundle.JobDetail.Key.Name to decide which specific class to build
return _container.ResolveKeyed<IJob>(bundle.JobDetail.Key.Name);
}
public void ReturnJob(IJob job)
{
}
}
在 IScheduler 部分
var container = builder.Build(); sched.JobFactory = new AutofacJobFactory(container); // start the schedule sched.Start();
當然 Autofac 端註冊實也要記得 IJob 跟實作 class 的對應,還有建構子參數的傳入等
builder.RegisterAssemblyTypes(asmCollToReg.ToArray())
.Where(t => t.Name == typeImplIJob.Name) // decide to build which IJob Impl class's instance
.Keyed<IJob>(typeImplIJob.Name) // para match to class name
.WithParameter("input", typeImplIJob.Name + " :D"); // para for ctor, para1 is variable name
GitHub: full proj
ref:DI&Quartz、ctor para、 condition of RegisterAssemblyTypes
沒有留言:
張貼留言