quartz.net 如何实现动态job ,appdomain 域卸载问题

2020-12-03 15:49发布

问题:

想实现类似插件一样的job,然后支持新增和删除。反射加载dll的话无法释放的,本地dll也无法删除。

删除任务时,顺便把任务所在的dll删除,如果不用appdomain的话,dll无法删除。

但使用appdomain的话,创建任务时无法识别是ijob类型,只有System.MarshalByRefObject 造成创建任务失败。

 var type =Job.GetType();

IJobDetail jobDetail = JobBuilder.Create(type).WithIdentity(key).UsingJobData("ServerName", scheduler.SchedulerName)
.Build();//JobBuilder.Create(type) 使用appdomain后这一句报错。

回答1:

 [Serializable]
    public class ProxyObject1 : MarshalByRefObject
    {

        private Assembly assembly = null;

        public void LoadAssembly(string path)
        {

            assembly = Assembly.LoadFile(path);
        }

        public void AddJob(string jobName, string jobGoupName, string cron)
        {
            var obj = assembly.CreateInstance("TaskDll.TestDll");
            var t = (Quartz.IJob)obj;
            JobInfo info = new JobInfo();
            info.Job = t;
            info.JobGroupName = jobGoupName;
            info.JobName = jobName;
            info.StartTime = DateTime.Now;
            info.EndTime = DateTime.MaxValue;
            info.CronExpress = cron;

            QuartzHelper.Add(info);
        }
    }
 AppDomainSetup setup = new AppDomainSetup();
            setup.ShadowCopyFiles = "true";
            var domain = AppDomain.CreateDomain(dllPath, null, setup);
            var loc = Assembly.GetExecutingAssembly().Location;
            var obj = (ProxyObject1)domain.CreateInstanceFromAndUnwrap(loc, "xx.ProxyObject1");
            obj.LoadAssembly(dllPath);
            obj.AddJob(jobName, jobGroupName, Cron);


回答2:

  1. 创建一个新的appdomain, 加载你的新job.
  2. 主程序中创建一个新的jobetail, 从新的job或者配置信息. 自定义的接口支持MarshalByRefObject.
    3.主程序的job触发,执行自定义的dll里面的定义的job.

伪代码:

JobOptions : MarshalByRefObject {
static string jobname;
static string cron;
static void execute(); //job要执行的方法, 主程序保存对这个对象的引用, 然后达到触发条件后 invoke这个方法.
}
//主程序
var ad =appdomain.createdomain();
var ass = ad.load(your new job dll);
var (newjobname, newjobcron, newjobmethod)= ass.gettype("JobOptions").invoke(....)
var newjob= new jobwarpper(newjobname, newjobcron, newjobmethod);
JobBuilder.create(newjob... tirgger...);