Раньше я думал, что создание объектов во время выполнения будет лучшим подходом. Теперь я менее уверен, так как вы теряете некоторые полезные функции, хотя это может стоить того, что было бы просто для предотвращения путаницы новичков. Недостатками этого являются:
1. Производительность
def foo(arg=something_expensive_to_compute())):
...
Если используется оценка времени вызова, тогда дорогая функция вызывается каждый раз, когда ваша функция используется без аргумента. Вы либо заплатили бы дорогостоящую цену за каждый вызов, либо должны вручную кэшировать значение извне, загрязняя пространство имен и добавляя многословие.
2. Принудительные связанные параметры
Полезный трюк заключается в привязке параметров лямбда к привязке current переменной при создании лямбда. Например:
funcs = [ lambda i=i: i for i in range(10)]
Возвращает список функций, возвращающих 0,1,2,3 ... соответственно. Если поведение изменено, они вместо этого привяжут i
к значению времени вызова для i, поэтому вы получите список функций, которые все вернули 9
.
Единственным способом реализации этого в противном случае было бы создать дальнейшее закрытие с привязкой i, то есть:
def make_func(i): return lambda: i
funcs = [make_func(i) for i in range(10)]
3. Introspection
Рассмотрим код:
def foo(a='test', b=100, c=[]):
print a,b,c
Мы можем получить информацию о аргументах и значениях по умолчанию с помощью модуля inspect
, который
>>> inspect.getargspec(foo)
(['a', 'b', 'c'], None, None, ('test', 100, []))
информация очень полезна для таких вещей, как создание документов, метапрограммирование, декораторы и т. д.
Теперь предположим, что поведение по умолчанию может быть изменено так, что это эквивалентно:
_undefined = object() # sentinel value
def foo(a=_undefined, b=_undefined, c=_undefined)
if a is _undefined: a='test'
if b is _undefined: b=100
if c is _undefined: c=[]
Однако мы потеряли способность интроспекции и посмотрим, какие аргументы по умолчанию равны . Поскольку объекты не были построены, мы никогда не сможем их захватить, не называя функцию. Самое лучшее, что мы могли бы сделать, это сохранить исходный код и вернуть его как строку.
Когда вы планируете задание, вы можете установить JobDataMap
на объект JobDetail
и передать его вашему планировщику, есть некоторые ограничения, описанные в учебнике quartz.net . Задание может получить доступ к данным через:
JobDataMap dataMap = context.JobDetail.JobDataMap;
Однако я предпочитаю получать доступ к моей конфигурации заданий через репозиторий, введенный в задание.
У меня были неожиданные результаты с ответом Hillstuk выше в многопоточных средах. Вот мое решение, использующее Newtonsoft ... Наслаждайтесь
public void InitJob() {
MyClass data = new MyClass {Foo = “Foo fighters”};
/* a unique identifier for demonstration purposes.. Use your own concoction here. */
int uniqueIdentifier = new Random().Next(int.MinValue, int.MaxValue);
IJobDetail newJob = JobBuilder.Create<MyAwesomeJob>()
.UsingJobData("JobData", JsonConvert.SerializeObject(data))
.WithIdentity($"job-{uniqueIdentifier}", "main")
.Build();
}
/* the execute method */
public class MyAwesomeJob : IJob
{
public void Execute(IJobExecutionContext context)
{
var jobData = JsonConvert.DeserializeObject<MyClass>(context.JobDetail.JobDataMap.GetString("JobData"));
}
}
/* for completeness */
public class MyClass {
string Foo { get; set; }
}
Есть два способа передать объект, который можно получить при выполнении задания Quartz:
Передайте экземпляр в карте данных. Когда вы установите задание вверх, добавьте свой экземпляр на карту с таким ключом:
// Create job etc...
var MyClass _myInstance;
statusJob.JobDataMap.Put("myKey", _myInstance);
// Schedule job...
Извлеките экземпляр в методе Execute()
задания следующим образом:
public void Execute(IJobExecutionContext context)
{
var dataMap = context.MergedJobDataMap;
var myInstance = (MyClass)dataMap["myKey"];
ИЛИ
Добавьте экземпляр в контекст планировщика, когда вы установите задание вверх, например:
ISchedulerFactory schedFact = new StdSchedulerFactory();
_sched = schedFact.GetScheduler();
_sched.Start();
// Create job etc...
var MyClass _myInstance;
_sched.Context.Put("myKey", myInstance);
// Schedule job...
Извлеките экземпляр в методе Execute()
для задания следующим образом:
public void Execute(IJobExecutionContext context)
{
var schedulerContext = context.Scheduler.Context;
var myInstance = (MyClass)schedulerContext.Get("myKey");
[Serializable]
?
– Dejan
24 March 2015 в 16:11
Вы можете поместить ваш экземпляр / объект в файл IJobDetail.
JobDataMap m = new JobDataMap();
m.Put("Class1", new Class1(){name="xxx"});
IJobDetail job = JobBuilder.Create<Job>()
.WithIdentity("myJob", "group1")
.UsingJobData(m)//class object
.UsingJobData("name2", "Hello World!")
.Build();
использование
public void Execute(IJobExecutionContext context)
{
JobDataMap dataMap = context.JobDetail.JobDataMap;
Class1 class1 = (Class1)dataMap.Get("Class1");
string x = class1.name;
}
Я передал объект следующим образом
JobDetail job1 = JobBuilder.newJob(JobAutomation.class)
.usingJobData("path", path)
.withIdentity("job2", "group2").build();
CronTrigger trigger1 = TriggerBuilder.newTrigger()
.withIdentity("cronTrigger2", "group2")
.withSchedule(CronScheduleBuilder.cronSchedule("40 27 11 * * ?"))
.build();
получить jobdatamap следующими строками кода
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String path =dataMap.getString("path");