IOptionsMonitor 与 IOptionsSnapshot 之间的区别
Difference between IOptionsMonitor vs. IOptionsSnapshot
根据,IOptionsMonitor
在DI容器中注册为单例并且能够通过OnChange
事件订阅检测变化。它有一个 CurrentValue
属性.
另一方面,IOptionsSnapshot
被注册为 scoped 并且还具有通过读取每个请求的最后选项来检测变化的能力,但它没有有 OnChange
事件。它有一个 Value
属性.
例如,将两者都注入到视图中会给我们完全相同的行为:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using UsingOptionsSample.Models;
using UsingOptionsSample.Services;
namespace UsingOptionsSample.Pages
{
public class MyOptions
{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}
public string Option1 { get; set; }
public int Option2 { get; set; } = 5;
}
public class OptionsTestModel : PageModel
{
private readonly MyOptions _snapshotOptions;
private readonly MyOptions _monitorOptions;
public OptionsTestModel(
IOptionsMonitor<MyOptions> monitorOptionsAcessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor)
{
_snapshotOptions = snapshotOptionsAccessor.Value;
_monitorOptions = monitorOptionsAcessor.CurrentValue;
}
public string SnapshotOptions { get; private set; }
public string MonitorOptions { get; private set; }
public void OnGetAsync()
{
//Snapshot options
var snapshotOption1 = _snapshotOptions.Option1;
var snapshotOption2 = _snapshotOptions.Option2;
SnapshotOptions =
$"snapshot option1 = {snapshotOption1}, " +
$"snapshot option2 = {snapshotOption2}";
//Monitor options
var monitorOption1 = _monitorOptions.Option1;
var monitorOption2 = _monitorOptions.Option2;
MonitorOptions =
$"monitor option1 = {monitorOption1}, " +
$"monitor option2 = {monitorOption2}";
}
}
}
那么,如果这两个 interfaces/implementations 看起来是一样的,只是生命周期不同,那有什么意义呢?代码是 based on this sample,令人惊讶的是它不包含 IOptionsMonitor
用法示例。
如果两个 return 一个选项的“当前值”,为什么一个有“值”属性 而另一个有“当前值”?
Why/when 我应该使用 IOptionsSnapshot
而不是 IOptionsMonitor
吗?
我想我没弄清楚,我一定是遗漏了一些关于这些和依赖注入的非常重要的方面。
评论已经有一些很好的答案了。尝试和 summarize/repeat 曾:
IOptionsSnapshot
非常适合注入到作用域或瞬态对象中。它将在该对象的生命周期内保持一致,并且在您获得新对象时会出现新值。
但是,如果您需要在单例中重新加载的选项,您应该使用 IOptionsMonitor
,因为您的单例永远不会改变。此类服务的一个很好的例子是从 IHostedService
继承的服务,用于 ASP.NET 核心中的长期 运行 后台服务。
IOptionsMonitor
是一个单例服务,可以随时检索当前选项值,这在单例依赖中特别有用。
IOptionsSnapshot
是一项 范围内的服务 并在 IOptionsSnapshot<T>
时提供选项的 快照 对象被构建。选项快照设计用于 transient 和 scoped 依赖项。
Use IOptions<T>
when you are not expecting your config values to
change. Use IOptionsSnaphot<T>
when you are expecting your values to
change but want it to be consistent for the entirety of a request. Use
IOptionsMonitor<T>
when you need real time values.
在我的项目中,我需要从配置中读取一些值并将它们与身份验证令牌数据合并。因此,我将 IOptionsSnapshot
用于 Scoped 存储,并且必须更新只读 Value
属性。没问题,每隔 属性:
更新一次
IOptionsMonitor<Company> companyConfig
...
_companyConfig.Value.CompanyName = "...";
根据IOptionsMonitor
在DI容器中注册为单例并且能够通过OnChange
事件订阅检测变化。它有一个 CurrentValue
属性.
另一方面,IOptionsSnapshot
被注册为 scoped 并且还具有通过读取每个请求的最后选项来检测变化的能力,但它没有有 OnChange
事件。它有一个 Value
属性.
例如,将两者都注入到视图中会给我们完全相同的行为:
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using UsingOptionsSample.Models;
using UsingOptionsSample.Services;
namespace UsingOptionsSample.Pages
{
public class MyOptions
{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}
public string Option1 { get; set; }
public int Option2 { get; set; } = 5;
}
public class OptionsTestModel : PageModel
{
private readonly MyOptions _snapshotOptions;
private readonly MyOptions _monitorOptions;
public OptionsTestModel(
IOptionsMonitor<MyOptions> monitorOptionsAcessor,
IOptionsSnapshot<MyOptions> snapshotOptionsAccessor)
{
_snapshotOptions = snapshotOptionsAccessor.Value;
_monitorOptions = monitorOptionsAcessor.CurrentValue;
}
public string SnapshotOptions { get; private set; }
public string MonitorOptions { get; private set; }
public void OnGetAsync()
{
//Snapshot options
var snapshotOption1 = _snapshotOptions.Option1;
var snapshotOption2 = _snapshotOptions.Option2;
SnapshotOptions =
$"snapshot option1 = {snapshotOption1}, " +
$"snapshot option2 = {snapshotOption2}";
//Monitor options
var monitorOption1 = _monitorOptions.Option1;
var monitorOption2 = _monitorOptions.Option2;
MonitorOptions =
$"monitor option1 = {monitorOption1}, " +
$"monitor option2 = {monitorOption2}";
}
}
}
那么,如果这两个 interfaces/implementations 看起来是一样的,只是生命周期不同,那有什么意义呢?代码是 based on this sample,令人惊讶的是它不包含 IOptionsMonitor
用法示例。
如果两个 return 一个选项的“当前值”,为什么一个有“值”属性 而另一个有“当前值”?
Why/when 我应该使用 IOptionsSnapshot
而不是 IOptionsMonitor
吗?
我想我没弄清楚,我一定是遗漏了一些关于这些和依赖注入的非常重要的方面。
评论已经有一些很好的答案了。尝试和 summarize/repeat 曾:
IOptionsSnapshot
非常适合注入到作用域或瞬态对象中。它将在该对象的生命周期内保持一致,并且在您获得新对象时会出现新值。
但是,如果您需要在单例中重新加载的选项,您应该使用 IOptionsMonitor
,因为您的单例永远不会改变。此类服务的一个很好的例子是从 IHostedService
继承的服务,用于 ASP.NET 核心中的长期 运行 后台服务。
IOptionsMonitor
是一个单例服务,可以随时检索当前选项值,这在单例依赖中特别有用。
IOptionsSnapshot
是一项 范围内的服务 并在 IOptionsSnapshot<T>
时提供选项的 快照 对象被构建。选项快照设计用于 transient 和 scoped 依赖项。
Use
IOptions<T>
when you are not expecting your config values to change. UseIOptionsSnaphot<T>
when you are expecting your values to change but want it to be consistent for the entirety of a request. UseIOptionsMonitor<T>
when you need real time values.
在我的项目中,我需要从配置中读取一些值并将它们与身份验证令牌数据合并。因此,我将 IOptionsSnapshot
用于 Scoped 存储,并且必须更新只读 Value
属性。没问题,每隔 属性:
IOptionsMonitor<Company> companyConfig
...
_companyConfig.Value.CompanyName = "...";