在 asp.net Core (3+) 中配置服务注册时的依赖注入访问
Dependency Injection Access While Configuring Service Registrations in asp.net Core (3+)
我有一些案例,我想根据在依赖注入容器中注册的对象来配置服务。
例如,我有以下 WS Federation 注册:
authenticationBuilder.AddWsFederation((options) =>{
options.MetadataAddress = "...";
options.Wtrealm = "...";
options.[...]=...
});
我在上述案例中的目标是使用一个配置对象,它可以通过 DI 容器来配置 WsFederation 中间件。
在我看来 IPostConfigureOptions<>
是要走的路,但直到现在,我还没有找到实现此目标的方法。
这怎么能做到,或者不可能?
I(Post)ConfigureOptions<T>
方法见https://andrewlock.net/simplifying-dependency-injection-for-iconfigureoptions-with-the-configureoptions-helper/,但我觉得那样太麻烦了。
我一般用这个模式:
// Get my custom config section
var fooSettingsSection = configuration.GetSection("Foo");
// Parse it to my custom section's settings class
var fooSettings = fooSettingsSection.Get<FooSettings>()
?? throw new ArgumentException("Foo not configured");
// Register it for services who ask for an IOptions<FooSettings>
services.Configure<FooSettings>(fooSettings);
// Use the settings instance
services.AddSomeOtherService(options => {
ServiceFoo = fooSettings.ServiceFoo;
})
更明确一点,但是您的所有配置和 DI 代码都集中在一个地方。
当然这会完全绕过 I(Post)ConfigureOptions<T>
,因此如果之后有其他代码使用这些接口修改 FooSettings
,我的代码将不会注意到它,因为它直接从配置中读取文件。鉴于我控制 FooSettings
及其用户,这对我来说没问题。
如果您确实想使用该界面,这应该是方法:
首先,注册您要从中提取设置的自定义配置部分:
var fooSettingsSection = configuration.GetSection("Foo");
services.Configure<FooSettings>(fooSettingsSection);
然后,创建一个选项配置器:
public class ConfigureWSFedFromFooSettingsOptions
: IPostConfigureOptions<Microsoft.AspNetCore.Authentication.WsFederation.WsFederationOptions>
{
private readonly FooSettings _fooSettings;
public ConfigureWSFedFromFooSettingsOptions(IOptions<FooSettings> fooSettings)
{
_fooSettings = fooSettings.Value;
}
public void Configure(WsFederationOptions options)
{
options.MetadataAddress = _fooSettings.WsFedMetadataAddress;
options.Wtrealm = _fooSettings.WsFedWtRealm;
}
}
最后 link 东西放在一起:
services.AddTransient<IPostConfigureOptions<WsFederationOptions>, ConfigureWSFedFromFooSettingsOptions>();
配置器将注入您的 IOptions<FooSettings>
,从应用程序设置实例化,然后用于进一步配置 WsFederationOptions
。
我有一些案例,我想根据在依赖注入容器中注册的对象来配置服务。 例如,我有以下 WS Federation 注册:
authenticationBuilder.AddWsFederation((options) =>{
options.MetadataAddress = "...";
options.Wtrealm = "...";
options.[...]=...
});
我在上述案例中的目标是使用一个配置对象,它可以通过 DI 容器来配置 WsFederation 中间件。
在我看来 IPostConfigureOptions<>
是要走的路,但直到现在,我还没有找到实现此目标的方法。
这怎么能做到,或者不可能?
I(Post)ConfigureOptions<T>
方法见https://andrewlock.net/simplifying-dependency-injection-for-iconfigureoptions-with-the-configureoptions-helper/,但我觉得那样太麻烦了。
我一般用这个模式:
// Get my custom config section
var fooSettingsSection = configuration.GetSection("Foo");
// Parse it to my custom section's settings class
var fooSettings = fooSettingsSection.Get<FooSettings>()
?? throw new ArgumentException("Foo not configured");
// Register it for services who ask for an IOptions<FooSettings>
services.Configure<FooSettings>(fooSettings);
// Use the settings instance
services.AddSomeOtherService(options => {
ServiceFoo = fooSettings.ServiceFoo;
})
更明确一点,但是您的所有配置和 DI 代码都集中在一个地方。
当然这会完全绕过 I(Post)ConfigureOptions<T>
,因此如果之后有其他代码使用这些接口修改 FooSettings
,我的代码将不会注意到它,因为它直接从配置中读取文件。鉴于我控制 FooSettings
及其用户,这对我来说没问题。
如果您确实想使用该界面,这应该是方法:
首先,注册您要从中提取设置的自定义配置部分:
var fooSettingsSection = configuration.GetSection("Foo");
services.Configure<FooSettings>(fooSettingsSection);
然后,创建一个选项配置器:
public class ConfigureWSFedFromFooSettingsOptions
: IPostConfigureOptions<Microsoft.AspNetCore.Authentication.WsFederation.WsFederationOptions>
{
private readonly FooSettings _fooSettings;
public ConfigureWSFedFromFooSettingsOptions(IOptions<FooSettings> fooSettings)
{
_fooSettings = fooSettings.Value;
}
public void Configure(WsFederationOptions options)
{
options.MetadataAddress = _fooSettings.WsFedMetadataAddress;
options.Wtrealm = _fooSettings.WsFedWtRealm;
}
}
最后 link 东西放在一起:
services.AddTransient<IPostConfigureOptions<WsFederationOptions>, ConfigureWSFedFromFooSettingsOptions>();
配置器将注入您的 IOptions<FooSettings>
,从应用程序设置实例化,然后用于进一步配置 WsFederationOptions
。