2011-02-05 2 views
12

Есть ли у кого-нибудь опыт интеграции autofac и Quartz.Net? Если да, то где лучше всего управлять пожизненным управлением - IJobFactory, в Execute из IJob или через прослушиватели событий?Autofac и Quartz.Net Integration


Прямо сейчас, я использую пользовательский autofac IJobFactory для создания IJob экземпляров, но у меня нет простой способ подключить к ILifetimeScope в IJobFactory, чтобы обеспечить любые дорогие ресурсы, которые впрыскивают в IJob очищаются. Завод-изготовитель просто создает экземпляр задания и возвращает его. Вот мои текущие идеи (надеюсь, есть лучшие из них ...)

  • Похоже, большинство AutoFac интеграций каким-то образом обернуть ILifetimeScope вокруг единицы работы, которую они создают. Очевидным способом грубой силы является передача ILifetimeScope в IJob и метод Execute создать дочерний элемент ILifetimeScope и создать экземпляры любых зависимостей там. Это кажется слишком близким к шаблону локатора сервисов, который, в свою очередь, кажется, противоречит духу autofac, но это может быть самый очевидный способ обеспечить правильную обработку области.

  • Я мог подключиться к некоторым событиям кварца, чтобы обрабатывать различные этапы стека выполнения задания и управлять им в течение жизни. Вероятно, это будет намного больше работы, но, возможно, стоит того, если будет более чистое разделение проблем.

  • Убедитесь, что IJob простая обертка вокруг IServiceComponent типа, который будет делать всю работу, и просить его как Owned<T> или Func<Owned<T>>. Мне нравится, как это, похоже, больше влияет на autofac, но мне не нравится, что он не является строго обязательным для всех разработчиков IJob.

ответ

12

Не зная слишком много о Quartz.Net и IJob с, рискну предложение по-прежнему.

Рассмотрим следующую работы обертку:

public class JobWrapper<T>: IJob where T:IJob 
{ 
    private Func<Owned<T>> _jobFactory; 

    public JobWrapper(Func<Owned<T>> jobFactory) 
    { 
     _jobFactory = jobFactory; 
    } 


    void IJob.Execute() 
    { 
     using (var ownedJob = _jobFactory()) 
     { 
      var theJob = ownedJob.Value; 
      theJob.Execute(); 
     } 
    } 
} 

Учитывая следующие регистрации:

builder.RegisterGeneric(typeof(JobWrapper<>)); 
builder.RegisterType<SomeJob>(); 

Задание завод теперь может решить эту обертку:

var job = _container.Resolve<JobWrapper<SomeJob>>(); 

Примечание:lifetime scope будет cre как часть экземпляра ownedJob, который в этом случае имеет тип Owned<SomeJob>. Любые зависимости, требуемые SomeJob, то есть InstancePerLifetimeScope или InstancePerDependency, будут созданы и уничтожены вместе с экземпляром Owned.

+0

спасибо, что нашли время, чтобы ответить. Мне нравится идея в том, что это более явная версия моего третьего мозгового штурма в исходном вопросе.Меня все еще беспокоит то, что я не могу контролировать всю жизнь. В принципе, я хотел бы запускать каждый IJob в своем собственном «LifetimeScope», почти как эквивалент вызова службы WCF. Кварц 'IJobFactory', к сожалению, в значительной степени ожесточен и забыл о том, что я смог рассказать, поэтому может случиться так, что, если мне действительно нужны явные границы границ, мне придется заглянуть в систему слушателей кварца. –

+0

@dfaivre - я исправил ошибку в своем коде, я забыл часть 'ownedJob.Value'. Возможно, теперь мои намерения более ясны. –

+3

Я не знал, что Owned создал область; очень полезно. Я думаю, что это, вероятно, самый прямой подход, без глубокого погружения в стек кварца. Я, вероятно, добавлю свой «IJobFactory», чтобы выбросить, если задание не относится к типу 'JobWrapper <>' (просто так я сплю немного лучше ночью). Еще раз спасибо за великолепное понимание. –