L' IServiceCollection
interfaccia viene utilizzata per la creazione di un contenitore di iniezione di dipendenza. Dopo che è stato completamente creato, viene composto in IServiceProvider
un'istanza che è possibile utilizzare per risolvere i servizi. Puoi iniettare un IServiceProvider
in qualsiasi classe. Le classi IApplicationBuilder
e HttpContext
possono fornire anche il fornitore di servizi, rispettivamente tramite le loro proprietà ApplicationServices
o RequestServices
.
IServiceProvider
definisce un GetService(Type type)
metodo per risolvere un servizio:
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
Esistono anche diversi metodi di estensione della convenienza, come serviceProvider.GetService<IFooService>()
(aggiungi un using
per Microsoft.Extensions.DependencyInjection
).
Risoluzione dei servizi all'interno della classe di avvio
Iniezione di dipendenze
Hosting provider di servizi del runtime può iniettare alcuni servizi nel costruttore della Startup
classe, come ad esempio IConfiguration
,
IWebHostEnvironment
( IHostingEnvironment
in pre-3.0 versioni), ILoggerFactory
e IServiceProvider
. Si noti che quest'ultima è un'istanza creata dal livello di hosting e contiene solo i servizi essenziali per l'avvio di un'applicazione .
Il ConfigureServices()
metodo non consente l'iniezione di servizi, accetta solo un IServiceCollection
argomento. Questo ha senso perché ConfigureServices()
è dove registri i servizi richiesti dalla tua applicazione. Tuttavia, è possibile utilizzare i servizi iniettati nel costruttore di avvio qui, ad esempio:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
Tutti i servizi registrati ConfigureServices()
possono quindi essere inseriti nel Configure()
metodo; puoi aggiungere un numero arbitrario di servizi dopo il IApplicationBuilder
parametro:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
Risolvere dipendenze manualmente
Se è necessario risolvere manualmente i servizi, è preferibile utilizzare il metodo ApplicationServices
fornito da IApplicationBuilder
nel Configure()
metodo:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
È possibile passare e utilizzare direttamente un IServiceProvider
nel costruttore della tua Startup
classe, ma come sopra conterrà un sottoinsieme limitato di servizi e quindi ha un'utilità limitata:
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
Se è necessario risolvere i servizi nel ConfigureServices()
metodo, è necessario un approccio diverso. È possibile costruire un intermedio IServiceProvider
dal IServiceCollection
grado che contiene i servizi che sono stati registrati fino a quel momento :
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>();
}
Nota: in
genere dovresti evitare di risolvere i servizi all'interno del ConfigureServices()
metodo, poiché in realtà questo è il luogo in cui stai configurando i servizi dell'applicazione. A volte hai solo bisogno di accedere a IOptions<MyOptions>
un'istanza. È possibile ottenere ciò vincolando i valori IConfiguration
dall'istanza a un'istanza di MyOptions
(che è essenzialmente ciò che fa il framework delle opzioni):
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
I servizi di risoluzione manuale (aka Service Locator) sono generalmente considerati un anti-schema . Sebbene abbia i suoi casi d'uso (per framework e / o livelli di infrastruttura), dovresti evitarlo il più possibile.