简体   繁体   中英

Using Ninject to inject IJob from external assembly into Quartz.net scheduler

I'm trying to create an application that can load external assemblies using Ninject and run them on a schedule using Quartz.net.

I have successfully implemented Quartz.net to be injected itself and run jobs based off classes implemented with IJob, from within the same assembly. This works well.

I would like to take it one step further and create a plugin architecture.

I have created a generic interface that all plugins will use, IPlugin, this interface also implements IJob. This is complied and referenced in the main application and each plugin implements it.

using Quartz;

namespace PluginFramework
{
    public interface IPlugin : IJob
    { }
}


Then I have a test plugin that implements IPlugin. Very straightforward, it just outputs a timestamp in green.

using System;
using PluginFramework;
using Quartz;

namespace TestPlugin
{
    public class Plugin : IPlugin
    {
        public void Execute(IJobExecutionContext context)
        {
            Start();
        }

        private void Start()
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine(DateTime.Now + " - PLUGIN 1");
        }
    }
}


Before I added the Quartz.net framework, I would load and execute the plugin like so. The plugin would load, run once and the application would end, as expected.

var kernel = new StandardKernel();

var assemblies = Directory.GetFiles(@"E:\Plugins\", "*.dll");

foreach (var assembley in assemblies)
{
    kernel.Load(assembley);
}

var plugins = kernel.GetAll<IPlugin>();

foreach (var plugin in plugins)
{
    plugin.Execute();
}


Now I need the plugin to run on a schedule, but it must still be loaded via Ninject and the main application should remain agnostic to the type, it should just know it's an IJob and be able to run it on a schedule defined in some configuration. This is the bit I am having trouble with.

I have my NinjectJobFactory

public class NinjectJobFactory : IJobFactory
{
    private IKernel Kernel { get; set; }

    public NinjectJobFactory(IKernel kernel)
    {
        Kernel = kernel;
    }

    public IJob NewJob(TriggerFiredBundle bundle)
    {
        return (IJob)Kernel.Get(bundle.JobDetail.JobType);
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return (IJob) Kernel.Get(bundle.JobDetail.JobType);
    }

    public void ReturnJob(IJob job)
    {

    }
}


My factory provider and scheduler provider.

public class QuartzSchedulerFactoryProvider : Provider<ISchedulerFactory>
{
    protected override ISchedulerFactory CreateInstance(IContext context)
    {
        var properties = new NameValueCollection();
        var section = (NameValueCollection)ConfigurationManager.GetSection("quartz");

        properties["quartz.scheduler.instanceName"] = section["quartz.scheduler.instanceName"];
        properties["quartz.threadPool.type"] = section["quartz.threadPool.type"];
        properties["quartz.threadPool.threadCount"] = section["quartz.threadPool.threadCount"];
        properties["quartz.threadPool.threadPriority"] = section["quartz.threadPool.threadPriority"];
        properties["quartz.jobStore.type"] = section["quartz.jobStore.type"];
        properties["quartz.plugin.xml.type"] = section["quartz.plugin.xml.type"];
        properties["quartz.plugin.xml.fileNames"] = section["quartz.plugin.xml.fileNames"];

        return new StdSchedulerFactory(properties);
    }
}


public class QuartzSchedulerProvider : Provider<IScheduler>
{
    private readonly IJobFactory _jobFactory;
    private readonly IEnumerable<ISchedulerListener> _listeners;
    private readonly ISchedulerFactory _schedulerFactory;

    public QuartzSchedulerProvider(
        ISchedulerFactory schedulerFactory,
        IJobFactory jobFactory,
        IEnumerable<ISchedulerListener> listeners)
    {
        _jobFactory = jobFactory;
        _listeners = listeners;
        _schedulerFactory = schedulerFactory;
    }

    protected override IScheduler CreateInstance(IContext context)
    {
        var scheduler = _schedulerFactory.GetScheduler();
        scheduler.JobFactory = _jobFactory;

        foreach (var listener in _listeners)
        {
            scheduler.ListenerManager.AddSchedulerListener(listener);
        }

        return scheduler;
    }
}

and some configuration in an external XML file.

<schedule>
    <job>
        <name>Plugin1</name>
        <group>Plugins</group>
        <description></description>
        <job-type>TestPlugin.Plugin, TestPlugin</job-type>
        <durable>true</durable>
        <recover>false</recover>
    </job>

    <trigger>
        <simple>
            <name>Plugin1</name>
            <group>Plugins</group>
            <job-name>Plugin1</job-name>
            <job-group>Plugins</job-group>
            <misfire-instruction>SmartPolicy</misfire-instruction>
            <repeat-count>-1</repeat-count>
            <repeat-interval>1000</repeat-interval>
        </simple>
    </trigger>
</schedule>


Basically I'm not sure how to do it. I've tried a few things based on things I've found on Google/here, but nothing really helped. Any advice would be much appreciated.

如果要通过Ninject使用动态模块加载,请在页面底部查看并在这些自定义插件程序集中设置模块(ninject模块)以设置您的实现,它将自动执行您想要的操作。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM