Muh*_*eed 67 c# inversion-of-control asp.net-core-mvc asp.net-core
是否可以IOptions<AppSettings>
从ConfigureServices
Startup中的方法解析实例?通常,您可以使用IServiceProvider
初始化实例,但在注册服务时此阶段没有实例.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(
configuration.GetConfigurationSection(nameof(AppSettings)));
// How can I resolve IOptions<AppSettings> here?
}
Run Code Online (Sandbox Code Playgroud)
Hen*_*ema 112
您可以使用以下BuildServiceProvider()
方法构建服务提供者IServiceCollection
:
public void ConfigureService(IServiceCollection services)
{
// Configure the services
services.AddTransient<IFooService, FooServiceImpl>();
services.Configure<AppSettings>(configuration.GetSection(nameof(AppSettings)));
// Build an intermediate service provider
var sp = services.BuildServiceProvider();
// Resolve the services from the service provider
var fooService = sp.GetService<IFooService>();
var options = sp.GetService<IOptions<AppSettings>>();
}
Run Code Online (Sandbox Code Playgroud)
你需要这个Microsoft.Extensions.DependencyInjection
包.
在您只需要绑定某些选项的情况下ConfigureServices
,您还可以使用以下Bind
方法:
var appSettings = new AppSettings();
configuration.GetSection(nameof(AppSettings)).Bind(appSettings);
Run Code Online (Sandbox Code Playgroud)
此功能可通过Microsoft.Extensions.Configuration.Binder
包获得.
Ian*_*emp 18
告诉您手动构建IServiceProvider
以获取IOptions<T>
实例的所有其他答案都很危险,因为它们是错误的(至少从 ASP.NET Core 3.0 开始)!事实上,如果您今天使用这些答案,您将收到以下编译器警告:
从应用程序代码调用“BuildServiceProvider”会导致创建一个额外的单例服务副本。考虑替代方案,例如将依赖注入服务作为“配置”的参数。
正确的方法是实现这一点,在所有版本的 ASP.NET Core 中安全可靠地工作,是实现IConfigureOptions<TOptions>
自 .NET Core 1.0 以来就存在的接口 - 但似乎很少有人知道它是如何制作东西的工作™。
例如,您想要添加一个依赖于应用程序的其他服务之一的自定义模型验证器。最初似乎不可能 - 无法解决,IMyServiceDependency
因为您无法访问IServiceProvider
:
public class MyModelValidatorProvider : IModelValidatorProvider
{
public MyModelValidatorProvider(IMyServiceDependency dependency)
{
...
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.ModelValidatorProviders.Add(new MyModelValidatorProvider(??????));
});
}
Run Code Online (Sandbox Code Playgroud)
但它的“魔法”IConfigureOptions<TOptions>
使它变得如此简单:
public class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
private IMyServiceDependency _dependency;
public MyMvcOptions(IMyServiceDependency dependency)
=> _dependency = dependency;
public void Configure(MvcOptions options)
=> options.ModelValidatorProviders.Add(new MyModelValidatorProvider(_dependency));
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
...
// or scoped, or transient, as necessary for your service
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
}
Run Code Online (Sandbox Code Playgroud)
本质上,您在Add***(***Options)
委托中完成的任何设置ConfigureServices
现在都移到了您的IConfigureOptions<TOptions>
类的Configure
方法中。然后,您以注册任何其他服务的相同方式注册选项,然后就可以了!
有关更多详细信息以及有关幕后工作原理的信息,我向您推荐始终出色的 Andrew Lock。
Ehs*_*edi 17
实例化依赖于其他服务的类的最佳方法是使用为您提供IServiceProvider的Add XXX重载。这样,您无需实例化中间服务提供商。
下面的示例演示如何在AddSingleton / AddTransient方法中使用此重载。
services.AddSingleton(serviceProvider =>
{
var options = serviceProvider.GetService<IOptions<AppSettings>>();
var foo = new Foo(options);
return foo ;
});
services.AddTransient(serviceProvider =>
{
var options = serviceProvider.GetService<IOptions<AppSettings>>();
var bar = new Bar(options);
return bar;
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
26843 次 |
最近记录: |