FleuntScheduler IJobFactory
устарела, но не заменяется другой точкой расширения.Хотя в официальной документации, похоже, отсутствует какое-либо описание того, как эффективно разрешить ваши задания из вашего DI-контейнера, точка зрения сопровождающего кажется, что вы регистрируете свои задания как закрытие .
Посколькуиспользование замыкания означает разрешение задания, его обертывание в область действия и регистрацию вашей работы в Simple Injector, наиболее практичным решением было бы перенести эту логику в метод расширения.Это может выглядеть так:
public static void AddFluentSchedulerJob<TJob>(
this Container container, Action<Schedule> schedule)
where TJob : class, IMyJob
{
container.Register<TJob>();
JobManager.AddJob(() =>
{
using (ThreadScopedLifestyle.BeginScope(container))
{
container.GetInstance<TJob>().Run();
}
},
schedule);
}
ПРИМЕЧАНИЕ. В этом примере используется ThreadScopedLifestyle
стиль жизни, поскольку именно это вы используете в своем вопросе.Однако AsyncScopedLifestyle
предпочтительнее, чем ThreadScopedLifestyle
, поскольку он работает как в однопоточном, так и в асинхронном сценариях.ThreadScopedLifestyle
полезен при работе в .NET 4.0.
В этом примере IMyJob
является абстракцией, определенной приложением.При этом вы не допускаете зависимости кода приложения от FluentScheduler.
Этот метод расширения можно использовать следующим образом:
container.AddFluentSchedulerJob<MyAwesomeJob>(s => s.ToRunEvery(5).Seconds());
Другими вариантами является использование (теперь устарело) IJobFactory
.Это требует ваших заданий для реализации интерфейса FluentScheduler IJob
.Сложность реализации фабрики заданий заключается в том, что вам нужно найти способ обернуть операцию в область действия.
Хитрость заключается в том, чтобы обернуть решение и выполнение вашей работы областью действия.Поскольку в FluentScheduler кажется, что точки перехвата ограничены, я понял, что единственный способ сделать это - изменить фабрику заданий таким образом, чтобы он возвращал декоратор, который откладывает создание реального задания до тех пор, пока не будет вызван метод Execute
декоратора.,Execute
декоратора может запустить область действия, разрешить реальную работу, выполнить эту задачу и утилизировать область внутри.
Вот фабрика, которая использует область действия:
public class SimpleInjectorJobFactory : IJobFactory
{
private readonly Container container;
public SimpleInjectorJobFactory(Container container) => this.container = container;
public IJob GetJobInstance<T>() where T : IJob
{
return new ThreadScopedJobDecorator(
this.container,
() => (IJob)this.container.GetInstance(typeof(T)));
}
private sealed class ThreadScopedJobDecorator : IJob
{
private readonly Container container;
private readonly Func<IJob> decorateeFactory;
public ThreadScopedJobDecorator(Container container, Func<IJob> decorateeFactory)
{
this.container = container;
this.decorateeFactory = decorateeFactory;
}
public void Execute()
{
using (ThreadScopedLifestyle.BeginScope(this.container))
{
this.decorateeFactory().Execute();
}
}
}
}
Вы можетеиспользуйте эту фабрику, установив JobManager.JobFactory
, как вы уже делаете:
JobManager.JobFactory = new SimpleInjectorJobFactory(container);