L' IServiceCollectioninterfaccia viene utilizzata per la creazione di un contenitore di iniezione di dipendenza. Dopo che è stato completamente creato, viene composto in IServiceProviderun'istanza che è possibile utilizzare per risolvere i servizi. Puoi iniettare un IServiceProviderin qualsiasi classe. Le classi IApplicationBuildere HttpContextpossono fornire anche il fornitore di servizi, rispettivamente tramite le loro proprietà ApplicationServiceso RequestServices.
IServiceProviderdefinisce 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 usingper 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 Startupclasse, come ad esempio IConfiguration,
IWebHostEnvironment( IHostingEnvironmentin pre-3.0 versioni), ILoggerFactorye 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 IServiceCollectionargomento. 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 IApplicationBuilderparametro:
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 ApplicationServicesfornito da IApplicationBuildernel Configure()metodo:
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
È possibile passare e utilizzare direttamente un IServiceProvidernel costruttore della tua Startupclasse, 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 IServiceProviderdal IServiceCollectiongrado 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 IConfigurationdall'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.