老规矩:先把全部源码上传,见本文底部。
相对于Demo3的区别,就是能自动加载继承了IJob的任务,任务主体程序分离。
在exe执行文件的同级下建一个MyJobs的文件夹,每次会自动扫描该文件夹下的Job,添加到系统中来。
举例如下:现在有两个在系统中的任务。
复制一个编译好的Job dll文件放在MyJobs 按下工具菜单栏中的扫描,会有一个新增的任务出现。(是不影响其它正在执行的任务哦)
好了,图贴完,现在将下面几个技术要点。
1. 动态加载dll
IRun getRun; public void NewRun<T>() where T:IJob { getRun = new SimpleRunner<T>(); }
try { string dir = System.AppDomain.CurrentDomain.BaseDirectory + "MyJobs"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } DirectoryInfo TheFolder = new DirectoryInfo(dir); foreach (FileInfo fi in TheFolder.GetFiles())//遍历文件夹下所有文件 { string extension = Path.GetExtension(fi.FullName);//扩展名 ".aspx" if (extension == ".dll") { #region 获取jobs string path = fi.FullName;//dir + "\\Wpf.Quart.MyJobs.dll"; Assembly asm = Assembly.LoadFile(path); //Assembly asm = Assembly.GetExecutingAssembly(); Type[] types = asm.GetTypes(); foreach (Type t in types) { if (new ArrayList(t.GetInterfaces()).Contains(typeof(IJob))) { IJob job = ObjectUtils.InstantiateType<IJob>(t); if (job != null) { MethodInfo mi = this.GetType().GetMethod("NewRun").MakeGenericMethod(new Type[] { t }); mi.Invoke(this, null); IRun run = getRun; if (TaskRuns.Where(p => p.GetType() == run.GetType()).Count() > 0) { continue; } if (run != null) { if (localRuns != null) { var localRun = localRuns.Where(p => p.Name == run.Name).FirstOrDefault(); if (localRun != null) { CopyHelper.LeftCopyRight(run, localRun); } } if (run.TriggerState != TriggerState.Normal || run.Mode == Mode.Hand) { run.TriggerState = TriggerState.None; } run.CronSecondSet.Init(); run.CronMinuteSet.Init(); run.CronHourSet.Init(); run.CronDaySet.Init(); run.CronMonthSet.Init(); run.CronWeekSet.Init(); run.CronYearSet.Init(); run.LogOut = this.LogOut; run.IsEdit = false; TaskRuns.Add(run); } } } } #endregion } } } catch (Exception ex) { log.Fatal(ex); }
二.分离出几个关键的接口放到另一个库中,需要实现的任务加载那个dll库就行。主要用来显示的,如果你的任务不用显示,那么可以不需要这几个接口,直接继承IJob就行
public class JobHelper { public static IJobRun GetRun(IJobExecutionContext context) { JobDataMap data = context.JobDetail.JobDataMap; IJobRun Run = data.Get("Runner") as IJobRun; if (Run != null) { Run.GetNextRunTimes(); } return Run; } }
public interface IJobRun { string CronExpression { get; set; } TriggerState TriggerState { get; set; } string SettingStr { get; set; } DateTime? StartTime { get; set; } DateTime? EndTime { get; set; } DateTime? NextRunTime { get; } DateTime[] NextRunTimes { get; set; } void GetNextRunTimes(); void Info(string message); void DEBUG(string message); void ERROR(string message); void FATAL(string message); void WARN(string message); }
三.具体任务的简单例子
public class MyHelloJobEx : IJob { public async Task Execute(IJobExecutionContext context) { await Console.Out.WriteLineAsync("HelloJob is executing."); var Run = JobHelper.GetRun(context); if (Run != null) { Run.Info("HelloJob is executing."); } } } //JobHelper主要是来界面显示日志,获取下次任务执行时间。不需要,可以不用。
最后补充一下,水平不足,有点乱,抱歉。
源码下载地址:链接:https://pan.baidu.com/s/15UD5oMia8REnYVtJE4_xHA
提取码:pexq