services.Configure<>() 还是 services.AddSingleton().Get()?

She*_*dPT 11 c# configuration asp.net-core

众所周知,有两种方法可以在 ASP.NET Core 2 中获取选项类:

  1. services.Configure<>()像这样使用:

    services.AddOption();
    services.Configure<ApplicationOptions>(Configuration.GetSection("applicationSettings"));
    
    Run Code Online (Sandbox Code Playgroud)
  2. services.AddSingleton(Configuration.Get())像这样使用:

    services.AddSingleton(Configuration.GetSection("applicationSettings")
        .Get<ApplicationOptions>());
    
    Run Code Online (Sandbox Code Playgroud)

但是这些不同的方法有什么优点或缺点?

pok*_*oke 18

使用Configure<ApplicationOptions>允许选项模式。选项模式是使用各种配置源配置事物的好方法。在您的示例中,您正在ApplicationOptions使用 Microsoft.Extensions.Configuration 源进行配置。但您也可以同时通过其他来源进行配置:

// configure using configuration
services.Configure<ApplicationOptions>(Configuration.GetSection("applicationSettings"));

// then apply a configuration function
services.Configure<ApplicationOptions>(options =>
{
    // overwrite previous values
    options.Foo = "bar";
});
Run Code Online (Sandbox Code Playgroud)

还有一些其他方法可以调整配置,例如使用后配置,它允许您轻松组合使用选项但可能需要建立某些默认值或回退的内容。

Option 对象将在它们被使用时进行配置,因此当您调用 时services.Configure(),实际上当时没有任何配置。相反,配置是在 DI 容器中注册的。And then, when the options are resolved, all configurations for a certain type will be invoked (which allows for composition). 这允许选项也支持更新配置;因此,当您appsettings.json在运行时更新时,选项能够接收更新后的值。

为了使用选项,您需要注入IOptions<ApplicationOptions>(或者IOptionsSnapshot<ApplicationOptions>如果您需要更新选项)。这是选项对象的包装器,它将调用选项模式。


另一方面,调用AddSingleton<ApplicationOptions>只是将单例实例注册为固定值。因此,在 DI 提供程序中注册的是在那个确切时刻Configuration.GetSection("applicationSettings").Get<ApplicationOptions>()返回的任何值。

这样做的好处是您不需要使用选项模式;不必注入IOptions<ApplicationOptions>到你的类型中,你可以直接依赖ApplicationOptions。因此,您不会依赖于 Options 框架。这对于想要在默认情况下选项模式可能不可用的不同场景中使用的独立库很有用。

但是,由于这会注册一个固定实例,因此您也仅限于这些确切值。当配置源更改时,您不能稍后更新这些值,也不能将该配置源与其他配置结合使用。


itm*_*nus 10

简短回答: 第一种方式添加一个Options,第二种方式注册一个普通的单例服务

如果可能,我总是更喜欢选项模式

在幕后,Configure<TOptions>()将调用services.AddSingleton<>()注册单例服务来配置选项。但是,要配置选项,我们应该始终使用第一种方式。因为Configure<TOptions>(config)(以及所有其他configure<>()方法)将为我们完成所有繁重的工作。:

  1. 例如,如果我们想为同一类型存储两个不同的实例,我们如何使用普通的单例服务来做到这一点?事实上,这正是命名选项所做的。

  2. 此外,很难根据文件更改自动重新加载普通的单例服务applicationSettings.json