如何使用 Quartz.net 和 log4net 配置 ninject
How to configure ninject with Quartz.net and log4net
我尝试让 quartz
和 log4net
与 ninject
一起工作。
Ninject
和 log4net
(没有 quartz
)效果完美。
但是当我使用 Quartz
时,作业已执行但记录器不工作。 (空控制台)
下面是Ninject
配置:
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<ILog>().ToMethod(x => LogManager.GetLogger(x.Request.Target != null
? x.Request.Target.Member.DeclaringType
: x.Request.Service));
kernel.Bind<IScheduler>().ToMethod(x =>
{
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
var sched = schedulerFactory.GetScheduler().Result;
sched.JobFactory = new NinjectJobFactory(kernel);
return sched;
});
和 ninjetJobFactory:
class NinjectJobFactory : SimpleJobFactory
{
readonly IKernel _kernel;
public NinjectJobFactory(IKernel kernel)
{
this._kernel = kernel;
}
public override IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
// this will inject dependencies that the job requires
return (IJob)this._kernel.Get(bundle.JobDetail.JobType);
}
catch (Exception e)
{
throw new SchedulerException(string.Format("Problem while instantiating job '{0}' from the NinjectJobFactory.", bundle.JobDetail.Key), e);
}
}
}
我用 this article 让 Quarts
和 ninject 一起工作。
我做了simple working example,你可以去github下载测试
感谢您的帮助。
在调查这个问题时,我意识到在解析调度程序之前简单地从内核解析 ILog
似乎可行。至于我有点不确定的原因。
不过,我确实注意到所使用的 Quartz 版本具有异步功能 API,因此在我调查问题期间必须进行一些更改。
在 link 文档的评论中,建议重构为新的异步 API 语法
kernel.Bind<Task<IScheduler>>().ToMethod(async _ => {
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
var sched = await schedulerFactory.GetScheduler();
sched.JobFactory = new NinjectJobFactory(kernel);
return sched;
});
我通过创建一个在启动调度程序时利用异步 API 优势的服务对此进行了改进。
public interface IService {
Task Start();
}
public class Service : IService {
private readonly IJobFactory jobFactory;
private readonly ILog log;
private readonly ISchedulerFactory schedulerFactory;
public Service(IJobFactory jobFactory, ISchedulerFactory schedulerFactory, ILog log) {
this.jobFactory = jobFactory;
this.schedulerFactory = schedulerFactory;
this.log = log;
}
public async Task Start() {
IScheduler scheduler = await schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
IJobDetail job = JobBuilder.Create()
.OfType<SimpleJob>()
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(3)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(job, trigger);
await scheduler.Start();
log.Debug("Scheduler started");
}
}
我创建了一个引导程序并使用 NinjectModule
s 来正确组织依赖注入
public class Bootstrapper {
public IKernel Init() {
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IServiceProvider>().ToConstant(kernel);
return kernel;
}
}
public class LoggingModule : NinjectModule {
public override void Load() {
Bind<ILog>()
.ToMethod(x => LogManager.GetLogger(
x.Request.Target != null ? x.Request.Target.Member.DeclaringType : x.Request.Service)
);
}
}
public class QuartzModule : NinjectModule {
public override void Load() {
Bind<IJobFactory>().To<NinjectJobFactory>();
Bind<ISchedulerFactory>().To<StdSchedulerFactory>();
Bind<IService>().To<Service>();
}
}
class NinjectJobFactory : IJobFactory {
readonly IServiceProvider provider;
public NinjectJobFactory(IServiceProvider provider) {
this.provider = provider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) {
IJobDetail jobDetail = bundle.JobDetail;
Type jobType = jobDetail.JobType;
try {
// this will inject any dependencies that the job requires
var value = (IJob)provider.GetService(jobType);
return value;
} catch (Exception e) {
throw new SchedulerException(string.Format("Problem while instantiating job '{0}' from the NinjectJobFactory.", bundle.JobDetail.Key), e);
}
}
/// <summary>
/// Allows the job factory to destroy/cleanup the job if needed.
/// No-op when using SimpleJobFactory.
/// </summary>
public void ReturnJob(IJob job) {
var disposable = job as IDisposable;
disposable?.Dispose();
}
}
经过修改并相应地更新主程序
class Program {
static void Main(string[] args) {
Bootstrapper bootstrapper = new Bootstrapper();
var kernel = bootstrapper.Init();
WithQuartz(kernel).GetAwaiter().GetResult();
Console.ReadKey();
}
public static Task WithQuartz(IKernel kernel) {
var service = kernel.Get<IService>();
return service.Start();
}
}
一切似乎都按预期工作。
我尝试让 quartz
和 log4net
与 ninject
一起工作。
Ninject
和 log4net
(没有 quartz
)效果完美。
但是当我使用 Quartz
时,作业已执行但记录器不工作。 (空控制台)
下面是Ninject
配置:
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<ILog>().ToMethod(x => LogManager.GetLogger(x.Request.Target != null
? x.Request.Target.Member.DeclaringType
: x.Request.Service));
kernel.Bind<IScheduler>().ToMethod(x =>
{
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
var sched = schedulerFactory.GetScheduler().Result;
sched.JobFactory = new NinjectJobFactory(kernel);
return sched;
});
和 ninjetJobFactory:
class NinjectJobFactory : SimpleJobFactory
{
readonly IKernel _kernel;
public NinjectJobFactory(IKernel kernel)
{
this._kernel = kernel;
}
public override IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
// this will inject dependencies that the job requires
return (IJob)this._kernel.Get(bundle.JobDetail.JobType);
}
catch (Exception e)
{
throw new SchedulerException(string.Format("Problem while instantiating job '{0}' from the NinjectJobFactory.", bundle.JobDetail.Key), e);
}
}
}
我用 this article 让 Quarts
和 ninject 一起工作。
我做了simple working example,你可以去github下载测试
感谢您的帮助。
在调查这个问题时,我意识到在解析调度程序之前简单地从内核解析 ILog
似乎可行。至于我有点不确定的原因。
不过,我确实注意到所使用的 Quartz 版本具有异步功能 API,因此在我调查问题期间必须进行一些更改。
在 link 文档的评论中,建议重构为新的异步 API 语法
kernel.Bind<Task<IScheduler>>().ToMethod(async _ => {
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
var sched = await schedulerFactory.GetScheduler();
sched.JobFactory = new NinjectJobFactory(kernel);
return sched;
});
我通过创建一个在启动调度程序时利用异步 API 优势的服务对此进行了改进。
public interface IService {
Task Start();
}
public class Service : IService {
private readonly IJobFactory jobFactory;
private readonly ILog log;
private readonly ISchedulerFactory schedulerFactory;
public Service(IJobFactory jobFactory, ISchedulerFactory schedulerFactory, ILog log) {
this.jobFactory = jobFactory;
this.schedulerFactory = schedulerFactory;
this.log = log;
}
public async Task Start() {
IScheduler scheduler = await schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
IJobDetail job = JobBuilder.Create()
.OfType<SimpleJob>()
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(3)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(job, trigger);
await scheduler.Start();
log.Debug("Scheduler started");
}
}
我创建了一个引导程序并使用 NinjectModule
s 来正确组织依赖注入
public class Bootstrapper {
public IKernel Init() {
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IServiceProvider>().ToConstant(kernel);
return kernel;
}
}
public class LoggingModule : NinjectModule {
public override void Load() {
Bind<ILog>()
.ToMethod(x => LogManager.GetLogger(
x.Request.Target != null ? x.Request.Target.Member.DeclaringType : x.Request.Service)
);
}
}
public class QuartzModule : NinjectModule {
public override void Load() {
Bind<IJobFactory>().To<NinjectJobFactory>();
Bind<ISchedulerFactory>().To<StdSchedulerFactory>();
Bind<IService>().To<Service>();
}
}
class NinjectJobFactory : IJobFactory {
readonly IServiceProvider provider;
public NinjectJobFactory(IServiceProvider provider) {
this.provider = provider;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) {
IJobDetail jobDetail = bundle.JobDetail;
Type jobType = jobDetail.JobType;
try {
// this will inject any dependencies that the job requires
var value = (IJob)provider.GetService(jobType);
return value;
} catch (Exception e) {
throw new SchedulerException(string.Format("Problem while instantiating job '{0}' from the NinjectJobFactory.", bundle.JobDetail.Key), e);
}
}
/// <summary>
/// Allows the job factory to destroy/cleanup the job if needed.
/// No-op when using SimpleJobFactory.
/// </summary>
public void ReturnJob(IJob job) {
var disposable = job as IDisposable;
disposable?.Dispose();
}
}
经过修改并相应地更新主程序
class Program {
static void Main(string[] args) {
Bootstrapper bootstrapper = new Bootstrapper();
var kernel = bootstrapper.Init();
WithQuartz(kernel).GetAwaiter().GetResult();
Console.ReadKey();
}
public static Task WithQuartz(IKernel kernel) {
var service = kernel.Get<IService>();
return service.Start();
}
}
一切似乎都按预期工作。