Search code examples
c#asp.net-mvcdependency-injectionninjectquartz.net

How to manage Ninject scope binding for objects used by both ASP.NET MVC and Quartz?


I have an ASP.NET MVC application, which runs several scheduled jobs with Quartz.

The project uses Entity Framework with a repository pattern. And in my MVC project, the binding for the AppContext and GenericRepository are InRequestScope:

Bind<AppContext>().ToSelf().InRequestScope();
Bind<IGenericRepository>().To<GenericRepository>().InRequestScope();

GenericRepository takes AppContext as its constructor argument, and the scoping here makes perfect sense for the MVC project. However the context and repository are also used by some of the Quartz jobs, and obviously, the above scope won't work for a Quartz job. For example:

public class SampleJob : IJob 
{
    public SampleJob(IGenericRepository repository)
    {
        // some code...
    }
}

Here I need to inject IGenericRepository with a different scope, perhaps an InThreadScope(). And I can do that with conditional binding for IGenericRepository as follows:

Bind<IGenericRepository>()
    .To<GenericRepository>()
    .InThreadScope()
    .WhenInjectedInto<SampleJob>();

Great! That should work....

Nope, because the AppContext that is injected into GenericRepository will still be in RequestScope, so I need a conditional binding for AppContext too. But how?? I can't do WhenInjectedInto because AppContext will always be injected into GenericRepository.

Any idea? Or if there is a better way to manage Quartz job scopes in a MVC application please do share :)


Solution

  • Ninject provides a generic InScope() method you can use to return your own custom object that defines the scope. I have used this in the past to first try to resolve a Request scope, and if there isn't one, return the current Thread as scope. this way you have a sort of "Hybrid" scope.