启动时应如何在ConfigurationServices ASP.NET Core 2.0中使用appsettings.json配置键/值? [英] How should I use appsettings.json config key/values in my ConfigurationServices ASP.NET Core 2.0 on startup?

查看:136
本文介绍了启动时应如何在ConfigurationServices ASP.NET Core 2.0中使用appsettings.json配置键/值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为ASP.NET Core 2.0应用程序/网站配置服务.

我希望以这种方法从我的 appsettings.json 文件中引用一些键/值.

我不确定我要走的路行吗?

  public void ConfigureServices(IServiceCollection服务){services.AddMvcCore().AddJsonFormatters().AddCors();var applicationSettings = Configuration.GetSection("Settings").Get< ApplicationSettings>();services.AddSingleton(applicationSettings);//**这是我最初遇到的,但仅是设置//DI/IOC中的值.//services.Configure<ApplicationSettings>(options => Configuration.GetSection("Settings")//.Bind(options));var foo = new Foo(applicationSettings.SomeSetting);services.AddSingleton(foo);} 

看看我如何手动添加一个单例,然后再从应用设置实例中引用一个值?

vs

只需配置...

那么,是不是行之有效,还是有一个特定的原因使之成为可能?

记住->我需要将我的设置注入控制器等...

解决方案

从技术上讲,您可以执行任一操作.在这两种情况下,您都已注册了配置,并且可以通过依赖关系注入来使用该配置,因此所有内容都可以依赖该配置并获取配置实例.

您还在那里使用集中设置的 Configuration ,因此您可以从那里的配置堆栈中获得所有好处,例如多个提供程序或特定于环境的替代.

但是,人们的青睐肯定已经转移到使用自定义配置的 IOptions 方式.这是最先进的技术",并且在整个ASP.NET Core中用于几乎所有内容.它还允许您切换到可以在运行时 更新的选项.这种功能非常强大,最终可能会有用(不一定针对您的单身人士情况,但可能还有其他用途).

设置起来也很容易,实际上比您尝试的要短:

  services.Configure< ApplicationSettings>(Configuration.GetSection("Settings")));services.AddSingleton< Foo>(); 

请注意,即使是单例,也不应显式创建它的新实例,而应由DI处理.如果您的类具有正确的构造函数,则无论如何将自动注入依赖项:

 公共类Foo{私有只读ApplicationSettings _settings;公共Foo(IOptions< ApplicationSettings>设置){_settings = settings.Value;}} 

当然, Foo 在这里也可以有更多的依赖项.由于它将由DI构造,因此您只需在构造函数中添加更多依赖项,而无需在某个地方更新某些 new 调用.


如果您需要使用取决于您的配置的设置来配置某些服务,则仍然不应直接在此处绑定您的配置.所有配置都是基于DI的,因此您只需要注入正确的东西即可; IConfigureOptions< T> .基本上就是后来为服务提供 IOptions< T> 的东西.在您的JWT情况下,可能看起来像这样:

 //而不是在此处传递选项配置委托…services.AddAuthentication().AddJwtBearer();//…我们注册了IConfigureOptions< JwtBearerOptions>反而services.AddSingleton< IConfigureOptions< JwtBearerOptions>,ConfigureJwtBearerOptions>();.//…ConfigureJwtBearerOptions可能看起来像这样:class ConfigureJwtBearerOptions:IConfigureOptions< JwtBearerOptions>{私有只读ApplicationSettings _settings;公共ConfigureJwtBearerOptions(IOptions< ApplicationSettings>设置){_settings = settings.Value;}公共无效的Configure(JwtBearerOptions选项){//在此处配置JwtBearerOptions,并使用您的ApplicationSettingsoptions.MetadataAddress = _settings.JwtMetadataAddress;}} 

与仅将委托传递给 AddJwtBearer()相比,这似乎不必要地冗长,但是请注意,当您传递该委托时,这正是幕后情况:将创建对象,该对象在 Configure()调用中调用您的委托.因此,实际上是一样的.

请注意,对于身份验证方案,您实际上可以设置 IConfigureNamedOptions< T> ,这几乎是同一回事,只是它可以基于名称配置选项.对于身份验证方案,这是方案名称,因此基本上您可以在 Configure()中检查方案名称,然后决定如何配置选项.


关于创建单例实例,尤其是昂贵的实例,我认为 ConfigureServices 是此类事情的错误位置.当整个DI基础结构还不存在时,在应用程序启动阶段的很早就调用了 ConfigureServices .因此,在创建实例时您不能依赖任何东西.我还认为, 不是您创建对象的工作,但您应该DI来处理它的创建,这样就可以控制它的生命周期.

如果您绝对需要控制实例的创建时间,我建议您为此使用生命周期事件:基本上,之后应用程序已正确设置但是之前出现第一个请求时,您请求服务实例并对其进行初始化.这样,您仍然可以完全依赖于DI,并且不会在第一个请求后就懒惰地创建它.

您可以在 Configure 方法中注册生命周期处理程序:

  public void Configure(IApplicationBuilder应用程序,IApplicationLifetime applicationLifetime){applicationLifetime.ApplicationStarted.Register(()=>{//应用程序已启动,请在此处请求单例以触发DI//创建实例app.ApplicationServices.GetService< ExpensiveSingleton>();});//…}} 

I'm trying to configure my services for an ASP.NET Core 2.0 app/website.

I wish to reference some key/values from my appsettings.json file, in this method.

I'm not sure if what I'm going is OK or not:

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

See how i'm manually adding a singleton and then later, referring a value from the app settings instance?

vs

just configuring ...

So, is either way OK or is there a specific reason for either/or?

Remember -> i'm going to need to inject my settings into controllers, etc...

解决方案

Technically, you can do either. In both cases, you have the configuration registered and available through dependency injection, so everything can depend on it and will get the configuration instance.

You are also using the centrally set up Configuration there, so you have all the benefits from the configuration stack there, e.g. multiple providers or environment specific overrides.

However, the favor has definitely moved to the IOptions way of consuming custom configuration. It’s the "state of the art" and used throughout ASP.NET Core for literally everything. It also allows you to switch to options that can be updated at runtime. That’s very powerful and might become useful eventually (not necessarily for your specific situation with the singleton, but maybe for something else).

It’s also really easy to set this up, actually shorter than what you tried:

services.Configure<ApplicationSettings>(Configuration.GetSection("Settings"));

services.AddSingleton<Foo>();

Note that, even for singletons, you shouldn’t explicitly create a new instance of it, but let DI handle that. If your class has the correct constructor, dependencies will be automatically injected anyway:

public class Foo
{
    private readonly ApplicationSettings _settings;

    public Foo (IOptions<ApplicationSettings> settings)
    {
        _settings = settings.Value;
    }
}

Of course, Foo can also have more dependencies here. Since it’s going to be constructed by DI, you can just add more dependencies in the constructor, without having to update some new call somewhere.


If you need to configure certain services with settings that depend on your configuration, you still should not bind your configuration there directly. All of configuration is DI-based, so you just need to inject the right thing; a IConfigureOptions<T>. That’s basically the thing that provides the IOptions<T> to services later. In your JWT case, this could look like this:

// 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;
    }
}

This might seem unnecessarily verbose compared to just passing a delegate to AddJwtBearer() but note that this is exactly what happens under the hood when you pass that delegate: An IConfigureOptions<JwtBearerOptions> object will be created that calls your delegate in the Configure() call. So this is really just the same.

Note that for authentication schemes, you might actually set up a IConfigureNamedOptions<T> instead, which is almost the same thing except it can configure the options based on a name. For authentication schemes, that is the scheme name, so basically you check the scheme name in Configure() and then decide how to configure your options.


As for creating singleton instances, especially expensive ones, I would argue that ConfigureServices is the wrong place for such a thing. ConfigureServices is called very early in the application startup phase, when the whole DI infrastructure does not exist yet. So you could not rely on anything when creating your instance. I would also argue that it is still not your job to create the object but you should DI handle the creation of it and as such give it also control over its lifecycle.

If you absolutely need to control when the instance is created, I would suggest you to use the lifecycle events for this: Basically, after the application has set up properly but before a first request comes in, you request the instance of your services and initialize it. That way, you can still have it fully depend on DI, and it won’t be created lazily with the first request.

You can register lifecycle handlers in the Configure method:

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

    // …
}


}

这篇关于启动时应如何在ConfigurationServices ASP.NET Core 2.0中使用appsettings.json配置键/值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆