gpt4 book ai didi

c# - 从 ConfigureServices 中使用 ASP.NET Core DI 解析实例

转载 作者:IT王子 更新时间:2023-10-29 03:29:23 25 4
gpt4 key购买 nike

如何使用 ASP.NET Core MVC 内置依赖注入(inject)框架手动解析类型?

设置容器非常简单:

public void ConfigureServices(IServiceCollection services)
{
// ...

services.AddTransient<ISomeService, SomeConcreteService>();
}

但是如何在不执行注入(inject)的情况下解析 ISomeService 呢?例如,我想这样做:

ISomeService service = services.Resolve<ISomeService>();

IServiceCollection 中没有这样的方法。

最佳答案

IServiceCollection 接口(interface)用于构建依赖注入(inject)容器。完全构建后,它会组合成一个 IServiceProvider 。可用于解析服务的实例。您可以注入(inject) IServiceProvider进入任何类(class)。 IApplicationBuilderHttpContext类也可以通过它们的 ApplicationServices 提供服务提供者。或 RequestServices 属性分别。

IServiceProvider定义一个 GetService(Type type) 解析服务的方法:

var service = (IFooService)serviceProvider.GetService(typeof(IFooService));

还有一些方便的扩展方法可用,例如 serviceProvider.GetService<IFooService>() (为 using 添加一个 Microsoft.Extensions.DependencyInjection)。

在启动类中解析服务

注入(inject)依赖

运行时的托管服务提供商可以将某些服务注入(inject) Startup 的构造函数中类,例如 IConfiguration , IWebHostEnvironment (在 3.0 之前的版本中为 IHostingEnvironment), ILoggerFactory IServiceProvider .请注意,后者是由托管层构建的实例,仅包含启动应用程序的基本服务

ConfigureServices()方法不允许注入(inject)服务,它只接受 IServiceCollection争论。这是有道理的,因为 ConfigureServices()是您注册应用程序所需服务的地方。但是,您可以在此处使用启动构造函数中注入(inject)的服务,例如:

public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}

ConfigureServices() 中注册的任何服务然后可以注入(inject) Configure()方法;您可以在 IApplicationBuilder 之后添加任意数量的服务参数:

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}

public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}

手动解决依赖

如果需要手动解析服务,最好使用ApplicationServicesIApplicationBuilder 提供在Configure()方法:

public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}

可以传递并直接使用 IServiceProvider在你的 Startup 的构造函数中类,但如上所述这将包含有限的服务子集,因此实用性有限:

public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}

如果您必须解决 ConfigureServices() 中的服务方法,需要不同的方法。您可以构建中间体 IServiceProvider来自 IServiceCollection包含到那时已注册的服务的实例:

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

请注意:通常你应该避免在 ConfigureServices() 中解析服务方法,因为这实际上是您配置应用程序服务的地方。有时您只需要访问 IOptions<MyOptions>实例。您可以通过绑定(bind) IConfiguration 中的值来完成此操作实例到 MyOptions 的实例(这实际上是选项框架所做的):

public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}

或者对 AddSingleton/AddScoped/AddTransient 使用重载:

// Works for AddScoped and AddTransient as well
services.AddSingleton<IBarService>(sp =>
{
var fooService = sp.GetRequiredService<IFooService>();
return new BarService(fooService);
}

手动解析服务(又名服务定位器)是 generally considered an anti-pattern .虽然它有其用例(用于框架和/或基础设施层),但您应该尽可能避免使用它。

关于c# - 从 ConfigureServices 中使用 ASP.NET Core DI 解析实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32459670/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com