1

我正在尝试创建一个可以使用 Ninject 加载外部程序集并使用 Quartz.net 按计划运行它们的应用程序。

我已经成功地实现了 Quartz.net 来注入自身,并在同一个程序集中运行基于 IJob 实现的类的作业。这很好用。

我想更进一步,创建一个插件架构。

我创建了一个所有插件都会使用的通用接口,IPlugin,这个接口也实现了 IJob。这在主应用程序中被编译和引用,每个插件都实现它。

using Quartz;

namespace PluginFramework
{
    public interface IPlugin : IJob
    { }
}


然后我有一个实现 IPlugin 的测试插件。非常简单,它只是输出一个绿色的时间戳。

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


在我添加 Quartz.net 框架之前,我会像这样加载和执行插件。插件将加载,运行一次,应用程序将按预期结束。

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


现在我需要插件按计划运行,但它仍然必须通过 Ninject 加载,并且主应用程序应该与类型无关,它应该只知道它是一个 IJob 并且能够按照在某些配置中定义的计划运行它. 这是我遇到的麻烦。

我有我的 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)
    {

    }
}


我的工厂提供商和调度程序提供商。

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

以及外部 XML 文件中的一些配置。

<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>


基本上我不知道该怎么做。我已经根据我在谷歌/这里找到的东西尝试了一些东西,但没有任何帮助。任何建议将不胜感激。

4

1 回答 1

0

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

于 2014-07-13T15:38:06.383 回答