FluentScheduler dependency injection in constructor
原文链接:https://www.thetopsites.net/article/50617160.shtml
I am experimenting with FluentScheduler for some background tasks in ASP.net Core API.
The job should send push notifications every day at a particular time interval based on few criteria. I had gone through the document and implemented a test functionality to print some output in the console window. It worked as expected with predicted time interval.
But the actual job I am going to do with that involves database context which provides necessary information to perform the criteria to send out the notifications.
My problem is I am unable to use constructor with parameter in MyJob class which is throwing missing method exception
PS: As per this article from Scott Hanselman, FluentScheduler seems to be quite famous but I could not get any help from online communities. But obviously, it's quite easy to grasp.
public class MyJob : IJob
{
private ApplicationDbContext _context;
public MyJob(ApplicationDbContext context)
{
_context = context;
}
public void Execute()
{
Console.WriteLine("Executed");
SendNotificationAsync();
}
private async Task SendNotificationAsync()
{
var overdues = _context.Borrow.Join(
_context.ApplicationUser,
b => b.ApplicationUserId,
a => a.Id,
(a, b) => new { a, b })
.Where(z => (z.a.ReturnedDate == null) && (z.a.BorrowApproval == 1))
.Where(z => z.a.ReturnDate.Date == new DateTime().Date.AddDays(1).Date)
.Select(z => new { z.a.ApplicationUserId, z.a.Book.ShortTitle, z.a.BorrowedDate, z.b.Token })
.ToList();
Console.WriteLine("Acknowledged");
foreach (var r in overdues)
{
string message = "You are running late! The book '" + r.ShortTitle + "' borrowed on '" + r.BorrowedDate + "' due tomorrow.";
Console.WriteLine(message);
await new PushNotificationService().sendAsync(r.Token, "Due Tomorrow!", message);
}
}
}
From the source code for IJob, it looks like your class that implements IJob needs to have a parameterless default constructor. Since FluentScheduler also supports lambdas, it may be easier to have your dependency injection library create your object, then call the Execute method like so:
var myJob = new MyJob(new ApplicationDbContext()); Schedule(() => myJob.Execute()).ToRunEvery(1).Days().At(21, 15);
Or call the constructor yourself:
// Schedule a job using a factory method and pass parameters to the constructor. Schedule(() => new MyJob(new ApplicationDbContext())).ToRunNow().AndEvery(2).Seconds();
FluentScheduler dependency injection in constructor, Net and much more using FluentScheduler I'm trying to use a Core 2.0+ ? I want to use my services and resolve them dependencies. You can use constructor injection for your jobs and get that seamless ASP.NET Core As you said, your job is registered with a scoped lifetime 'Web API Request'. This means that a instance of a dependency is created by the container per request and it is disposed when the request ends. Your job is running inside FluentScheduler and is not linked with any request.
Note - In the documentation it says not to use IJobFactory because it is going to be deprecated soon, but it is working for me in Production for past 3,4 months - https://github.com/fluentscheduler/FluentScheduler/issues/71
I am using Autofac and Fluent Scheduler in a Windows Console Application which uses TopShelf to run it as a Windows Service.
To use Dependency Injection in FluentScheduler you have to setup a Job Factory to resolve the dependencies.
So first setup a JobFactory by implementing IJobFactory
Like this -
public class MyJobFactory : IJobFactory
{
public IJob GetJobInstance<T>() where T : IJob
{
return MyContainer.GetJobInstance<T>();
}
}
Now in the Job Factory because I'm using Autofac I am setting up a Container which has 2 methods
1 - ConfigureDependencies() - Which is only called once to setup the Container:
2 - GetJobInstance() - Which is called by the MyJobFactory to resolve t a Job instance
public class MyContainer
{
public static IContainer Container { get; set; }
public static void ConfigureDependencies()
{
var builder = new ContainerBuilder();
// Jobs
builder.RegisterType<MyJob>().As<MyJob>();
// DB Contexts
// Others
Container = builder.Build();
}
public static IJob GetJobInstance<T>() where T : IJob
{
return Container.Resolve<T>();
}
}
Then when you Start you application/service, it will look something like this.
public void Start()
{
// Configure Dependency Injection
MyContainer.ConfigureDependencies();
// Setup the Fluent Scheduler -
JobManager.JobFactory = new MyJobFactory();
JobManager.UseUtcTime();
JobManager.Initialize(new MyJobRegistry());
}
Then I've created a Job by adding 2 constructors -
1 - Parameter-less
2 - The constructor with Injected Objects
e.g.
public class MyJob : IJob
{
public static string JobName = "MyJob";
private readonly ICompaniesProvider _companiesProvider;
// parameter-less constructor
public MyJob() { }
// injecting HERE
public MyJob(ICompaniesProvider companiesProvider)
{
_companiesProvider = companiesProvider;
}
public void Execute()
{
}
}
EDIT
Because of deprecated issue of IJobFactory, you could just call the Container Directly and get a Job Instance before adding it to the JobManager
public void Start()
{
// Configure Dependency Injection
MyContainer.ConfigureDependencies();
JobManager.UseUtcTime();
JobManager.Start();
var myJob = MyContainer.GetJobInstance<MyJob>();
Action<Schedule> schedule = s => s.ToRunEvery(1).Hours().At(0);
JobManager.AddJob(myJob, schedule);
}
本文探讨了在ASP.NET Core API中使用FluentScheduler进行后台任务调度时如何实现依赖注入。通过实例展示了如何配置Autofac容器并设置JobFactory来解决构造函数注入问题。
1430

被折叠的 条评论
为什么被折叠?



