我正在尝试为ASP.NET Core 2.0应用程序/网站配置我的服务。
我希望在此方法中引用appsettings.json
文件中的一些键/值。
我不确定我的目标是否正常:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddJsonFormatters()
.AddCors();
var applicationSettings = Configuration.GetSection("Settings").Get<ApplicationSettings>();
services.AddSingleton(applicationSettings);
// ** THIS IS WHAT I ORIGINALLY HAD, BUT IT'S ONLY SETTING
// THE VALUE IN DI/IOC.
//services.Configure<ApplicationSettings>(options => Configuration.GetSection("Settings")
// .Bind(options));
var foo = new Foo(applicationSettings.SomeSetting);
services.AddSingleton(foo);
}
了解我如何手动添加单例,然后再引用应用设置实例中的值?
VS
只是配置......
所以,无论哪种方式都好,或者是否存在/或?
的具体原因记住 - &gt;我需要将我的设置注入控制器等......
答案 0 :(得分:2)
从技术上讲,你可以做到。在这两种情况下,您都可以通过依赖注入注册和使用配置,因此一切都可以依赖于它并获得配置实例。
您还在那里使用集中设置Configuration
,因此您可以从配置堆栈获得所有好处,例如:多个提供者或特定于环境的覆盖。
然而,这种好处肯定转移到消费自定义配置的IOptions
方式。它是“最先进的”,并且在整个ASP.NET Core中用于所有内容。它还允许您切换到可在运行时更新的选项。这是非常强大的,最终可能会变得有用(不一定适用于单身人士的特定情况,但可能是其他的)。
设置它也很容易,实际上比你尝试的要短:
services.Configure<ApplicationSettings>(Configuration.GetSection("Settings"));
services.AddSingleton<Foo>();
请注意,即使对于单身人士,也不应该明确地创建它的新实例,而是让DI处理它。如果您的类具有正确的构造函数,则无论如何都将自动注入依赖项:
public class Foo
{
private readonly ApplicationSettings _settings;
public Foo (IOptions<ApplicationSettings> settings)
{
_settings = settings.Value;
}
}
当然,Foo
在这里也可以有更多的依赖关系。由于它将由DI构建,因此您只需在构造函数中添加更多依赖项,而无需在某处更新某些new
调用。
如果您需要使用取决于您的配置的设置来配置某些服务,您仍然不应该直接绑定您的配置。所有配置都是基于DI的,所以你只需注入正确的东西;一个IConfigureOptions<T>
。这基本上是稍后为服务提供IOptions<T>
的东西。在您的JWT案例中,这可能如下所示:
// instead of passing an option configuration delegate here…
services.AddAuthentication().AddJwtBearer();
// … we register a IConfigureOptions<JwtBearerOptions> instead
services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptions>();
// … ConfigureJwtBearerOptions could look like this:
class ConfigureJwtBearerOptions : IConfigureOptions<JwtBearerOptions>
{
private readonly ApplicationSettings _settings;
public ConfigureJwtBearerOptions(IOptions<ApplicationSettings> settings)
{
_settings = settings.Value;
}
public void Configure(JwtBearerOptions options)
{
// configure JwtBearerOptions here, and use your ApplicationSettings
options.MetadataAddress = _settings.JwtMetadataAddress;
}
}
与仅将委托传递给AddJwtBearer()
相比,这看起来可能显得过于冗长,但请注意,当您传递该委托时,这正是在幕后发生的事情:将创建一个调用您的IConfigureOptions<JwtBearerOptions>
对象在Configure()
电话中委托。所以这真的是一样的。
请注意,对于身份验证方案,您实际上可能会设置IConfigureNamedOptions<T>
,这几乎是相同的,除了它可以根据名称配置选项。对于身份验证方案,即方案名称,所以基本上您在Configure()
中检查方案名称,然后决定如何配置选项。
至于创建单例实例,特别是昂贵的实例,我认为ConfigureServices
对于这样的事情是错误的。在应用程序启动阶段很早就调用ConfigureServices
,此时整个DI基础架构尚不存在。所以在创建实例时你不能依赖任何东西。我还认为创建对象仍然不是你的工作,但你应该DI处理它的创建,因此它也可以控制它的生命周期。
如果您绝对需要来控制创建实例的时间,我建议您使用生命周期事件:基本上,在之后应用程序已正确设置但在第一个请求进入之前,您请求服务实例并初始化它。这样,您仍然可以完全依赖DI,并且不会在第一次请求时懒得创建。
您可以使用Configure
方法注册生命周期处理程序:
public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime)
{
applicationLifetime.ApplicationStarted.Register(() =>
{
// application has started, request the singleton here to trigger DI to
// create the instance
app.ApplicationServices.GetService<ExpensiveSingleton>();
});
// …
}
}
答案 1 :(得分:0)
这种方法的问题是,通过DI加载多个配置部分是不可能的。 Configuration API具有许多功能,例如可插拔配置提供,快照等。 我建议你至少使用一个类绑定你的配置部分,所以DI可以根据它的类型注入它。如果你需要另外一个配置类,你就不会遇到问题。
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration