5

I would like to be able to access the built-in IoC container (IServiceProvider I believe).

I know that it is generally bad practice to access this in code and that we should allow the framework to inject whichever dependencies are needed in to things like controllers.

My particular application for this is that I am using another product Hangfire. This framework instantiates objects itself. In order to have dependencies injected into these objects you need to override the JobActivator class and refer to your own container there.

This question shows how to create a new container for testing purposes, but I would like access to the one I have already set up and not have to duplicate it. With DI frameworks like Autofac you get access to the container when you build it after adding all the services.

Can anyone help?

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Zak
  • 361
  • 1
  • 5
  • 12
  • Your case is completely valid. Sometimes you need to delay or dispatch the creation of objects, and this means that you need to call back into the 'container'. As long as this callback is implemented inside the [Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot/), this is [absolutely fine](http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/). – Steven Feb 21 '17 at 10:36

1 Answers1

3

You can access the IServiceProvider during the configuration phase app.ApplicationServices or using the HttpContext.RequestServices. The custom JobActivator should look like:

public class AspNetCoreJobActivator : JobActivator
{
    private IServiceProvider _serviceProvider;

    public AspNetCoreJobActivator(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public AspNetCoreJobActivator(IHttpContextAccessor httpContextAccessor)
    {
        _serviceProvider = httpContextAccessor.HttpContext.RequestServices;
    }

    public AspNetCoreJobActivator(HttpContext context)
    {
        _serviceProvider = context.RequestServices;
    }

    public override object ActivateJob(Type type)
    {
        return _serviceProvider.GetService(type);
    }
}

In the Startup.cs file:

public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
    GlobalConfiguration.Configuration.UseActivator(new AspNetCoreJobActivator(serviceProvider)); // or app.ApplicationServices
    var server = new Hangfire.BackgroundJobServer();

    app.UseMvcWithDefaultRoute();
}
meziantou
  • 20,589
  • 7
  • 64
  • 83
  • Thanks. This is the way I ended up getting access to the service provider. I had different issues with Hangfire but that is for another time! :) – Zak Feb 27 '17 at 09:01