65.9K
CodeProject 正在变化。 阅读更多。
Home

Quartz.Net - 自定义基础 Job

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2012 年 6 月 7 日

CPOL

1分钟阅读

viewsIcon

43040

为 quartz 调度器开发创建自定义基础作业类

介绍 

Quartz.Net 允许你调度任务来运行。这些任务通常使用来自 JobDataMap 对象中的变量进行配置。我想要一个简单有效的类,它允许我使用 .NET 属性,而不是在需要调度任务时依赖于配置和设置 JobDataMap

背景 

一个重要的方面是我想要解决的是,虽然 Quartz.Net JobDataMap 类允许你存储对象,但我只想存储字符串值。问题是,如果你在 JobDataMap 中存储 .net 对象,你也会面临类型或版本问题的风险。

利用 Json.NET 框架,我构建了一个简单的 QuartzJobBase 类,它允许我只存储字符串值,但也允许我在 JobDataMap 中存储更复杂的对象。

使用代码

在开始之前,请确保你引用了 Json.NET 程序集。

QuartzJobBase 类是 Quartz.Net job 的抽象实现。它负责 3 个重要方面。

  1. 将当前属性值序列化到 JobDataMap
  2. 从 JobDataMap 反序列化属性值
  3. JobExecutionException 包装实现抛出的异常。

要将属性值序列化到 JobDataMap 中,你可以简单地在你的对象上调用 BuildJobDataMap() 来构建一个包含你当前属性值的 JobDataMap 实例。

对象的反序列化由类自动处理,因为它在 Quartz 调度器执行任务时执行。

using System;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;

namespace Quartz.Custom
{
    public abstract class QuartzJobBase : IJob
    {
        private static readonly Newtonsoft.Json.JsonSerializerSettings JsonSettings;
        static QuartzJobBase()
        {
            JsonSettings = new JsonSerializerSettings();
            JsonSettings.TypeNameHandling = TypeNameHandling.Auto;
            JsonSettings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
        }

        public void Execute(IJobExecutionContext context)
        {
            try
            {
                ReadFromJobDataMap(context.MergedJobDataMap);
                InternalExecute(context);
            }
            catch (Exception ex)
            {
                // Jobs should throw JobExecutionException if error occurred.
                // Wrap internal exceptions with JobExecutionException.
                JobExecutionException jex = new JobExecutionException(ex);
                throw jex;
            }
        }
        protected abstract void InternalExecute(IJobExecutionContext context);

        #region JobDataMap & Serialization
        
        public JobDataMap BuildJobDataMap()
        {
            JobDataMap data = new JobDataMap();

            foreach (var prop in GetType().GetProperties())
            {
                object value = prop.GetValue(this, null);
                string s = GetPropertyValue(prop);
                data.Add(prop.Name, s);
            }

            return data;
        }
        private void ReadFromJobDataMap(JobDataMap data)
        {
            PropertyInfo[] properties = GetType().GetProperties();

            foreach (var key in data.Keys)
            {
                var p = properties.Where(x => x.Name == key).SingleOrDefault();

                if (p != null)
                {
                    SetPropertyValue(p, data.GetString(key));
                }
            }
        }

        private string GetPropertyValue(PropertyInfo property)
        {
            object value = property.GetValue(this, null);
            return JsonConvert.SerializeObject(value, Formatting.None, JsonSettings);
        }
        private void SetPropertyValue(PropertyInfo property, string value)
        {
            object obj = JsonConvert.DeserializeObject(value, property.PropertyType, JsonSettings);
            property.SetValue(this, obj, null);
        }

        #endregion
    }
}

一个示例 job 实现如下所示。

 public class HelloWorldJob : QuartzJobBase
    {
        public string Name { get; set; }
        public int FavoriteNumber { get; set; }
        public List<string> CustomList { get; private set; }

        public HelloWorldJob()
        {
            CustomList = new List<string>();
        }

        protected override void InternalExecute(Quartz.IJobExecutionContext context)
        {
            Console.WriteLine("Hello World from {0} ({1})", Name, FavoriteNumber);

            foreach (var item in CustomList)
            {
                Console.WriteLine("{0} CUSTOM LIST: {1}", Name, item);
            }
        }
    } 

通过提供 JobDataMap 来调度任务

HelloWorldJob j = new HelloWorldJob();
j.Name = "My Name";
j.FavoriteNumber = r.Next(100);
for (int x = 0; x < 10; x++)
{
    j.CustomList.Add(r.Next().ToString());
}                

sched.ScheduleJob(
    JobBuilder.Create(typeof.HellowWorldJob)
    .UsingJobData(j.BuildJobDataMap())
    .Build(),
    TriggerBuilder.Create()
    .StartNow()
    .Build());

尽情享用!

© . All rights reserved.