IServiceCollection
Interfejs służy do budowy kontenera wtrysku zależność. Po pełnym skompilowaniu kompiluje się do IServiceProvider
instancji, której można użyć do rozwiązania usług. Możesz wstrzyknąć IServiceProvider
do dowolnej klasy. Te IApplicationBuilder
i HttpContext
klasy mogą zapewnić usługodawcy, jak również, za pośrednictwem swoich ApplicationServices
lub RequestServices
właściwości odpowiednio.
IServiceProvider
definiuje GetService(Type type)
metodę rozwiązania usługi:
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
Dostępnych jest również kilka metod rozszerzania wygody, takich jak serviceProvider.GetService<IFooService>()
(dodaj using
za Microsoft.Extensions.DependencyInjection
).
Rozwiązywanie usług w klasie startowej
Wstrzykiwanie zależności
Hosting usługodawca środowisko wykonawcze mogą wprowadzić pewne usługi do konstruktora Startup
klasy, takie jak IConfiguration
,
IWebHostEnvironment
( IHostingEnvironment
w wersji pre-3.0), ILoggerFactory
i IServiceProvider
. Pamiętaj, że ten ostatni jest instancją zbudowaną przez warstwę hostingu i zawiera tylko niezbędne usługi do uruchomienia aplikacji .
Ta ConfigureServices()
metoda nie zezwala na wstrzykiwanie usług, przyjmuje tylko IServiceCollection
argument. Ma to sens, ponieważ ConfigureServices()
rejestrujesz usługi wymagane przez aplikację. Można tu jednak skorzystać z usług wprowadzonych do konstruktora startupu, na przykład:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
Wszelkie zarejestrowane usługi ConfigureServices()
można następnie wprowadzić do Configure()
metody; możesz dodać dowolną liczbę usług po IApplicationBuilder
parametrze:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
Ręczne rozwiązywanie zależności
Jeśli trzeba ręcznie usług postanowienie, należy najlepiej użyć ApplicationServices
świadczone przez IApplicationBuilder
w Configure()
metodzie:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
Możliwe jest przekazanie i bezpośrednie użycie IServiceProvider
konstruktora Startup
klasy, ale jak wyżej, będzie on zawierał ograniczony podzbiór usług , a zatem ma ograniczoną użyteczność:
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
Jeśli musisz rozwiązać usługi w ConfigureServices()
metodzie, wymagane jest inne podejście. Możesz zbudować półprodukt IServiceProvider
z IServiceCollection
instancji, która zawiera usługi zarejestrowane do tego momentu :
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFooService, FooService>();
// Build the intermediate service provider
var sp = services.BuildServiceProvider();
// This will succeed.
var fooService = sp.GetService<IFooService>();
// This will fail (return null), as IBarService hasn't been registered yet.
var barService = sp.GetService<IBarService>();
}
Uwaga:
Zasadniczo należy unikać rozwiązywania usług w ramach ConfigureServices()
metody, ponieważ w rzeczywistości jest to miejsce, w którym konfigurujesz usługi aplikacji. Czasami potrzebujesz tylko dostępu do IOptions<MyOptions>
instancji. Możesz to zrobić, wiążąc wartości z IConfiguration
instancji z instancją MyOptions
(co jest zasadniczo tym, co robi struktura opcji):
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
Usługi ręcznego rozwiązywania problemów (zwane też lokalizatorem usług) są ogólnie uważane za anty-wzór . Chociaż ma swoje przypadki użycia (dla frameworków i / lub warstw infrastruktury), powinieneś unikać go w jak największym stopniu.