花了超過半天的時間歸結了數個類別之後,才找到問題,簡化來看,跑不起來的長的像
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
沒有留言:
張貼留言