如何在没有作业程序集的本地副本的情况下在 Quartz.net 中安排远程作业?

发布于 2024-11-17 04:30:25 字数 453 浏览 10 评论 0原文

我正在尝试创建一个远程作业以在 Quartz.net 中进行调度。当我在本地拥有包含作业的程序集的副本时,我可以执行类似的操作

    JobDetail job = new JobDetail("remotelyAddedJob", "default", typeof(DummyJob.DummyJob));

这要求我在服务器和我从中创建计划的计算机上都有包含 DummyJob 类的程序集的副本。

我想做的是能够在没有客户端组件副本的情况下创建计划,通过以存储在quartz_jobs.xml 文件中的方式发送作业类型信息,

  <job-type>Quartz.Job.NoOpJob, Quartz</job-type>

我一直无法弄清楚如何在没有本地副本的情况下发送类类型信息。有人对此有好的解决方案吗?

I'm trying to create a remote job for scheduling in Quartz.net. When I have a copy of the assembly containing the job locally I can do something like this

    JobDetail job = new JobDetail("remotelyAddedJob", "default", typeof(DummyJob.DummyJob));

This requires that I have a copy of the assembly containing the class DummyJob both on the server and on the computer I am creating the schedule from.

What I'd like to do is be able to create the schedule without a client-side copy of the assebmly, by sending the job-type information the way it is stored in the quartz_jobs.xml file

  <job-type>Quartz.Job.NoOpJob, Quartz</job-type>

I have not been able to figure out how to send the class type information without having a local copy. Does anyone have a good solution to this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

他夏了夏天 2024-11-24 04:30:25

这个问题真的很困扰我。我知道我可以动态生成类,所以我研究了如何生成。

第 1 步:创建此类

using System;
using Quartz;
using System.Reflection;
using System.Reflection.Emit;

namespace TestQuartzTaskCreator {
    public class FakeJob {
        public static Type Create(string assemblyName, string typeName){
            AssemblyName aName = new AssemblyName(assemblyName);
            AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
                    aName,
                    AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

            TypeBuilder tb = mb.DefineType(typeName, TypeAttributes.Public);

            tb.AddInterfaceImplementation(typeof(IJob));

            MethodBuilder meth = tb.DefineMethod(
                "Execute",
                MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(void),
                new Type[] { typeof(JobExecutionContext) });

            meth.DefineParameter(1,
                ParameterAttributes.In,
                "context");

            ILGenerator methIL = meth.GetILGenerator();
            methIL.Emit(OpCodes.Ldarg_0);

            Type t = null;
            try {
                // Finish the type.
                t = tb.CreateType();
            }
            catch (Exception ex) {
                System.Console.WriteLine(ex.ToString());
            }

//            ab.Save(aName.Name + ".dll");

            return t;
        }
    }
}

第 2 步:从此更改

JobDetail job = new JobDetail("remotelyAddedJob", "default", typeof(TestType));

JobDetail job = new JobDetail("remotelyAddedJob", "default", FakeJob.Create("TestAss", "TestType"));

第 3 步:像以前一样运行(但客户端中没有引用作业程序集的副本)

-- 编辑 --
虽然这实现了我最初想要的效果,但它并不能解决从客户端环境使用 Quartz.Net 时的所有问题。检索作业需要装配可用。

我当前的方法是创建一个 Web 服务接口,该接口将与服务驻留在同一服务器上,并提供一个更加断开连接的接口。

This problem was really bugging me. I knew that I could generate classes on the fly, so I looked into how.

Step 1: Create this class

using System;
using Quartz;
using System.Reflection;
using System.Reflection.Emit;

namespace TestQuartzTaskCreator {
    public class FakeJob {
        public static Type Create(string assemblyName, string typeName){
            AssemblyName aName = new AssemblyName(assemblyName);
            AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
                    aName,
                    AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

            TypeBuilder tb = mb.DefineType(typeName, TypeAttributes.Public);

            tb.AddInterfaceImplementation(typeof(IJob));

            MethodBuilder meth = tb.DefineMethod(
                "Execute",
                MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(void),
                new Type[] { typeof(JobExecutionContext) });

            meth.DefineParameter(1,
                ParameterAttributes.In,
                "context");

            ILGenerator methIL = meth.GetILGenerator();
            methIL.Emit(OpCodes.Ldarg_0);

            Type t = null;
            try {
                // Finish the type.
                t = tb.CreateType();
            }
            catch (Exception ex) {
                System.Console.WriteLine(ex.ToString());
            }

//            ab.Save(aName.Name + ".dll");

            return t;
        }
    }
}

Step 2: Change from this

JobDetail job = new JobDetail("remotelyAddedJob", "default", typeof(TestType));

to this

JobDetail job = new JobDetail("remotelyAddedJob", "default", FakeJob.Create("TestAss", "TestType"));

Step 3: Run as before (but without a copy of your job assembly being referenced in the client)

-- Edit --
While this did what I originally wanted it to, it doesn't resolve all of the issues when using Quartz.Net from a client environment. Retrieving the job requires that the assembly be available.

My current approach is to create a web-service interface that will reside on the same server as the service and present a more disconnected interface.

等你爱我 2024-11-24 04:30:25

Brad 的解决方案可能有效或部分有效,但似乎有一个更好的选择(没有这种动态类创建功夫):

  1. 在服务器端注册特定作业,无需任何触发器(Quartz.NET 允许您这样做),并使用特定的和唯一标识符;
  2. 在客户端为具有特定标识符的作业创建触发器(您不需要指定其类型 - 不需要在客户端上引用作业组装)和参数列表(如果需要),
  3. 如果需要使用参数在作业实例中使用 context.Trigger.JobData 而不是 context.JobDetails。

Brad's solution may work or partially work but there seems to be a better option (without this dynamic class creation Kung Fu):

  1. Register a specific job on the server side without any trigger (Quartz.NET allows you to do that) with a specific and unique identifier;
  2. On the client side create a trigger for a job with specific identifier (you do not need to specify its type - there is no need for a reference to job assembly on the client) and list of parameters if required,
  3. If you need to use parameters in the job instance use context.Trigger.JobData instead of context.JobDetails.

HERE you can find the source code which works in my project.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文