我有asp.net核心应用程序。我想使用IOptions
模式从appsettings.json注入值。所以我有一个类SecurityHeaderOptions
,并且还有目标类SecurityHeadersBuilder
,其构造函数将IOptions<SecurityHeaderOptions>
作为参数。
我知道.net core可以通过在注册容器后注入SecurityHeadersBuilder
来隐式创建IOptions<SecurityHeaderOptions>
的实例。
但是我想显式创建SecurityHeadersBuilder
的实例,调用其中一个方法,然后使用容器注册实例。
public sealed class SecurityHeaderOptions
{
public string FrameOption { get; set; }
public string XssProtection { get; set; }
}
public class SecurityHeadersBuilder
{
private readonly SecurityHeaderOptions _options = null;
public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
{
_options = options.Value;
}
public SecurityHeadersBuilder AddDefaultPolicy()
{
AddFrameOptions();
AddConetntSecurityPolicy();
return this;
}
}
配置服务方法
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));
services.AddScoped<SecurityHeadersBuilder>(provider =>
new SecurityHeadersBuilder(?????).AddDefaultPolicy())
}
问题
1 GT;如果我明确地将选项传递给构造函数,我是否需要使用SecurityHeaderOptions
方法向容器注册service.Configure
?
2 - ; Configuration.GetSection("SecurityHeaderOptions")
无法返回IOptions<SecurityHeaderOptions>
的实例,而是返回IConfigurationSection
?
3&gt;无论哪种方式,如何检索SecurityHeaderOptions
并将SecurityHeadersBuilder
传递给gsutil -m rm gs://mybucket/subbucket/*
的构造函数?
答案 0 :(得分:17)
使用.NET Core 2并在ConfigureServices
中没有提供程序(或希望添加它),我选择使用类似这样的东西(以OP代码为例):
public void ConfigureServices(IServiceCollection services)
{
// secOpts available for use in ConfigureServices
var secOpts = Configuration
.GetSection("SecurityHeaderOptions")
.Get<SecurityHeaderOptions>();
...
}
答案 1 :(得分:4)
这是我注册选项并注入SecurityHeadersBuilder
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));
services.AddScoped<SecurityHeadersBuilder>(provider =>
{
var option = provider.GetService<IOptions<SecurityHeaderOptions>>();
return new SecurityHeadersBuilder(option)
.AddDefaultPolicy();
});
}
答案 2 :(得分:1)
关于你的问题:
1。是的,您需要注册选项,但我相信您的选择方式是错误的(至少在您的示例中)。你应该注册为:
services.Configure<SecurityHeaderOptions>(options => Configuration.GetSection("SecurityHeaderOptions").Bind(options));
2。我相信上面提到的正确注册会返回您的期望。
3. 只需注册并将其放在SecurityHeaderBuilder
构造函数上即可。您不需要(默认的.NET Core IOC容器也不允许)在注册时传递构造函数参数。为此,您需要使用其他IOC,例如Autofac。
但您需要注册SecurityHeadersBuilder
才能在其他课程中使用它。
只需使用一个接口即可。
public interface ISecurityHeadersBuilder
{
SecurityHeadersBuilder AddDefaultPolicy;
}
public class SecurityHeadersBuilder : ISecurityHeadersBuilder
{
private readonly SecurityHeaderOptions _options = null;
public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
{
_options = options.Value;
}
public SecurityHeadersBuilder AddDefaultPolicy()
{
AddFrameOptions();
AddContentSecurityPolicy();
return this;
}
}
然后,只需在startup.cs
注册它
services.AddScoped<ISecurityHeadersBuilder, SecurityHeadersBuilder>();
答案 3 :(得分:1)
Docs 特别说:
<块引用>不要在 IOptions<TOptions>
中使用 IOptionsMonitor<TOptions>
或 Startup.ConfigureServices
。由于服务注册的顺序,可能存在不一致的选项状态。
因此您必须从 Startup.ConfigureServices
以其他方式访问配置,例如Quinton's answer
答案 4 :(得分:0)
首先,您需要向SecurityHeadersBuilder
添加第二个构造函数,该构造函数使用简单的SecurityHeaderOptions
:
public class SecurityHeadersBuilder
{
private readonly SecurityHeaderOptions _options;
public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
{
_options = options.Value;
}
public SecurityHeadersBuilder(SecurityHeaderOptions options)
{
_options = options;
}
public SecurityHeadersBuilder AddDefaultPolicy()
{
AddFrameOptions();
AddContentSecurityPolicy();
return this;
}
}
然后答案完全取决于您是否需要在Startup
类之外使用这些选项。
如果没有,则可以简单地使用Microsoft.Extensions.Configuration.ConfigurationBinder.Get<T>()
扩展方法:
services.AddScoped<SecurityHeadersBuilder>(provider =>
{
var options = Configuration.GetSection("SecurityHeaderOptions")
.Get<SecurityHeaderOptions>();
return new SecurityHeadersBuilder(options)
.AddDefaultPolicy();
});
(然后您可以删除采用SecurityHeadersBuilder
的{{1}}构造函数)。
如果您需要在其他地方使用这些选项,则可以将以上方法与IOptions<SecurityHeaderOptions>
扩展方法结合使用:
Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure()
答案 5 :(得分:0)
您可以这样做
public static class IConfigurationExtensions
{
public static TypedConfiguration<SecurityHeaderOptions> GetSecurityHeaderOptions(this IConfiguration configuration)
{
return new TypedConfiguration<SecurityHeaderOptions>(configuration.GetSection("SecurityHeaderOptions"));
}
}
public class TypedConfiguration<T> where T : class
{
public TypedConfiguration(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public T Value => Configuration.Get<T>();
public void InitializeOptions(IServiceCollection services)
{
services.Configure<T>(Configuration);
}
}
现在您已经从一个地方创建了一个对象,该对象同时具有IConfiguration
,类型为SecurityHeaderOptions
和用于为该类注册IOptions注入的辅助方法。
像这样使用它
public void ConfigureServices(IServiceCollection services)
{
var wrappedOptions = Configuration.GetSecurityHeaderOptions();
wrappedOptions.InitializeOptions(services);
var options = Options.Create(wrappedOptions.Value);
services.AddScoped<SecurityHeadersBuilder>(provider =>
new SecurityHeadersBuilder(options).AddDefaultPolicy());
}