Как получить экземпляр IServiceProvider в.NET Core?

IServiceProvider интерфейс с одним методом:

object GetService(Type serviceType);

Он используется для создания экземпляров типов, зарегистрированных в собственном DI-контейнере.NET Core.

Экземпляр IServiceProvider Сам можно получить, позвонив BuildServiceProvider метод IServiceCollection, IServiceCollection является параметром ConfigureServices метод в Startup учебный класс. Кажется, волшебным образом вызывается с экземпляром IServiceCollection по рамкам.

Я хочу создать экземпляр IServiceProvider без Setup метод вообще. Мне это нужно для разрешения зависимостей в сборке интеграционного теста. Возможно ли вообще получить его в этом сценарии?

8 ответов

Решение

Это реализация по умолчанию IServiceCollection от Microsoft: https://github.com/aspnet/DependencyInjection/blob/master/src/DI/ServiceCollection.cs

Глядя на код, вы сможете получить IServiceCollection просто позвонив:

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

Надеюсь, это поможет:)

Как упомянул козел, достаточно создать новый ServiceCollection, Вот пример класса, который можно использовать для доступа к контейнеру DI в.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 Класс взят из протестированного проекта, поэтому повторение регистрации услуг не требуется.

Тогда в тестовом классе просто используйте:

var foo = ServiceProviderFactory.ServiceProvider.GetServices(typeof(IFoo));

Чтобы получить доступ к существующему DI приложения ASP.NET Core, например, в каком-либо контроллере, вы должны зарегистрировать его в методе ConfigureServices файла Startup.cs:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddSingleton(services);   //  <- here

   // ... other DI registrations
   services.AddSingleton<IFooManager, FooManager>();
   services.AddTransient<IFooWorker, FooWorker>();
}

После этого вы можете использовать его в любых разрешенных объектах из DI следующим образом:

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
    }
}

Сначала вам нужно установить пакет NuGet https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection. (документы, API, API)

Затем вы создаете новый ServiceCollection и метод связать его с BuildServiceProvider метод. Между тем вы также можете зарегистрировать любого поставщика услуг.

var serviceProvider = new ServiceCollection()
    .AddSingleton<IFooService, FooService>()
    .BuildServiceProvider();

Вот обновленный подход:

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();

Пример использования:

host.Services.GetService<IFoo>();

Вы можете найти его в 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();
}

использовать этот ServiceProviderA = new ServiceCollection(). . . . . .BuildServiceProvider() .GetRequiredService<IServiceProvider>(); этот ServiceProviderA содержит себя

      public static class ServiceTool
{
    public static IServiceProvider ServiceProvider { get; private set; }
    public static IServiceCollection Create(IServiceCollection services)
    {
        ServiceProvider = services.BuildServiceProvider();
        return services;
    }
}
//set operations
services.AddSingleton(typeof(IRepository<>), typeof(EfRepository<,>));
ServiceTool.Create(services);  

//get operations
var rep = ServiceTool.ServiceProvider.GetService<IRepository<Account>>();
Другие вопросы по тегам