How to get an instance of IServiceProvider in .NET Core?

后端 未结 6 1707
不知归路
不知归路 2020-12-08 00:03

IServiceProvider is an interface with single method:

object GetService(Type serviceType);

It\'s used to create instances of ty

相关标签:
6条回答
  • 2020-12-08 00:30

    Here is an updated approach:

    var host = Host.CreateDefaultBuilder().ConfigureWebHostDefaults(builder =>
    {
        builder.ConfigureAppConfiguration((hostingContext, config) =>
        {
            var env = hostingContext.HostingEnvironment;
            env.ContentRootPath = Directory.GetCurrentDirectory();
            env.EnvironmentName = "Development";
        });
    
        builder.UseStartup<Startup>();
    }).Build();
    

    Example usage:

    host.Services.GetService<IFoo>();
    
    0 讨论(0)
  • 2020-12-08 00:34

    First you need to install the Microsoft.Extensions.DependencyInjection NuGet package. (docs, API, API)

    Then you create a new ServiceCollection and method chain it with the BuildServiceProvider method. In between that you can also register any service providers.

    var serviceProvider = new ServiceCollection()
        .AddSingleton<IFooService, FooService>()
        .BuildServiceProvider();
    
    0 讨论(0)
  • 2020-12-08 00:36

    You can find it in Program.cs

    public static IServiceProvider ServiceProvider { get; private set; }
    
    public static void Main(string[] args)
    {
        IHost build = CreateHostBuilder(args).Build();
        ServiceProvider = build.Services;
        build.Run();
    }
    
    0 讨论(0)
  • 2020-12-08 00:38

    To get access to existing DI of ASP.NET Core application e.g. in some controller, you should register it in ConfigureServices method of Startup.cs:

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
       services.AddMvc();
       services.AddSingleton(services);   //  <- here
    
       // ... other DI registrations
       services.AddSingleton<IFooManager, FooManager>();
       services.AddTransient<IFooWorker, FooWorker>();
    }
    

    After that, you can use it in any resolved objects from DI like this:

    public class FooManager: IFooManager
    {
        private readonly ServiceProvider _di;
    
        public FooManager(IServiceCollection serviceCollection)
        {
            _di = serviceCollection.BuildServiceProvider();
        }
    
        public void Start()
        {
            var w1 = _di.GetRequiredService<IFooWorker>();  // new instance of FooWorker
            var w2 = _di.GetRequiredService<IFooWorker>();  // new instance of FooWorker
        }
    }
    
    0 讨论(0)
  • 2020-12-08 00:42

    As goaty mentioned it's enough to create new ServiceCollection. Here's example class which can be used to access DI container in .NET Core:

    public static class ServiceProviderFactory
    {
        public static IServiceProvider ServiceProvider { get; }
    
        static ServiceProviderFactory()
        {
            HostingEnvironment env = new HostingEnvironment();
            env.ContentRootPath = Directory.GetCurrentDirectory();
            env.EnvironmentName = "Development";
    
            Startup startup = new Startup(env);
            ServiceCollection sc = new ServiceCollection();
            startup.ConfigureServices(sc);
            ServiceProvider = sc.BuildServiceProvider();
        }
    }
    

    Startup class is taken from tested project so the service registrations don't need to be repeated.

    Then in test class simply use:

    var foo = ServiceProviderFactory.ServiceProvider.GetServices(typeof(IFoo));
    
    0 讨论(0)
  • 2020-12-08 00:54

    This is the default implementation of IServiceCollection from Microsoft: https://github.com/aspnet/DependencyInjection/blob/master/src/DI/ServiceCollection.cs

    Looking at the code then you should be able to get an IServiceCollection simply by calling:

    var serviceCollection = new Microsoft.Extensions.DependencyInjection.ServiceCollection();
    

    Hope that helps :)

    0 讨论(0)
提交回复
热议问题