【问题标题】:How to configure ninject with Quartz.net and log4net如何使用 Quartz.net 和 log4net 配置 ninject
【发布时间】:2018-10-12 06:03:32
【问题描述】:

我尝试让quartzlog4netninject 一起工作。

Ninjectlog4net(没有 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上下载测试。

感谢您的帮助。

【问题讨论】:

  • 1.我使用控制台附加程序,控制台为空。 2.我在SimpleJob类中放断点,逐行调试
  • 是的,我使用 WithQuartz 时没有创建文件。
  • 我猜是调度程序调用的方法Execute,我不手动调用它
  • 对不起,我可能没理解正确,我为测试添加了 Console.writeLine("test"),并且工作正常,每 3 秒显示一次文本
  • 我发现这个thread 他们使用common.logging。我想我应该试试。

标签: c# dependency-injection ninject log4net quartz.net


【解决方案1】:

在调查该问题时,我意识到通过在解析调度程序之前简单地从内核解析 ILog 似乎可行。至于为什么我有点不确定。

但我确实注意到正在使用的 Quartz 版本具有异步 API,因此在我调查问题期间必须进行一些更改。

在链接文档的 cmets 中,建议重构为新的异步 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");
    }
}

我创建了一个引导程序并使用NinjectModules 来正确组织依赖注入

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();
    }
}

一切似乎都按预期工作。

【讨论】:

    猜你喜欢
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    相关资源
    最近更新 更多