Как получить экземпляр 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>>();