c# - 我应该如何在启动时在 ConfigurationServices ASP.NET Core 2.0 中使用 appsettings.json 配置键/值?

标签 c# asp.net asp.net-core

我正在尝试为 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);  
}

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

对比

刚刚配置...

那么,这两种方式都可以吗?或者是否有特定原因?

记住 -> 我需要将我的设置注入(inject) Controller 等......

最佳答案

从技术上讲,您可以选择其中任何一种。在这两种情况下,您都已通过依赖项注入(inject)注册并可用配置,因此一切都可以依赖它并获取配置实例。

您还使用集中设置的Configuration那里,所以你可以从那里的配置堆栈中获得所有好处,例如多个提供程序或特定于环境的覆盖。

但是,这种青睐肯定转移到了 IOptions 上。使用自定义配置的方式。它是“最先进的技术”,在 ASP.NET Core 中用于几乎所有的事情。它还允许您切换到可以在运行时更新的选项。这非常强大,最终可能会变得有用(不一定适用于单例的特定情况,但可能适用于其他情况)。

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

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

services.AddSingleton<Foo>();

请注意,即使对于单例,您也不应该显式创建它的新实例,而是让 DI 处理它。如果您的类具有正确的构造函数,则无论如何都会自动注入(inject)依赖项:

public class Foo
{
    private readonly ApplicationSettings _settings;

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

当然,Foo这里还可以有更多的依赖。由于它将由 DI 构建,因此您可以在构造函数中添加更多依赖项,而无需更新一些 new打电话到某个地方。


如果您需要使用取决于您的配置的设置来配置某些服务,您仍然不应该直接在那里绑定(bind)您的配置。所有配置都是基于DI的,所以你只需要注入(inject)正确的东西;一个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;
    }
}

与仅将委托(delegate)传递给 AddJwtBearer() 相比,这可能看起来不必要的冗长。但请注意,这正是当您传递该委托(delegate)时在后台发生的情况:An IConfigureOptions<JwtBearerOptions>将创建调用 Configure() 中的委托(delegate)的对象称呼。所以这实际上是一样的。

请注意,对于身份验证方案,您实际上可能会设置 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>();
    });

    // …
}


}

关于c# - 我应该如何在启动时在 ConfigurationServices ASP.NET Core 2.0 中使用 appsettings.json 配置键/值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46117430/

相关文章:

c# - 用于在运行时从接口(interface)生成具体类型的开源库?

jquery选择名称以x或y开头的输入

c# - 升级到 .net 5 程序集缺少框架版本

c# - 看不懂的语法,从vc++到c#

c# - 如何使用 rowdeleting 事件删除 gridview 中的行?

c# - 在 LINQ to SQL 中使用 contains()

jquery 拖放可在不同的 div 和 div 类之间排序

c# - 在单个页面中处理来自动态创建的控件的多个 "chained"回发

DOCKER_REGISTRY 值未设置构建错误

c# - ASP.Net Core 应用程序和 Environment.GetEnvironmentVariables() 奇怪的行为