IOptionsMonitor与IOptionsSnapshot之间的区别

nat*_*nho 16 dependency-injection interface options object-lifetime asp.net-core

根据此答案IOptionsMonitor将以单例形式注册在DI容器中,并且能够通过OnChange事件订阅来检测更改。它有一个CurrentValue属性。

另一方面,通过读取每个请求的最后一个选项IOptionsSnapshot被注册为作用域,并且还具有更改检测功能,但是它没有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}";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,如果这两个接口/实现看起来一样,只是寿命不同,那有什么意义呢?该代码基于此样本,令人惊讶的是其中不包含IOptionsMonitor使用样本。

如果一个都具有选项的“当前值”,为什么一个拥有“ Value”属性而另一个拥有“ CurrentValue”呢?

为什么/何时应该IOptionsSnapshot代替IOptionsMonitor

我认为我并没有直截了当,关于这些依赖项注入,我肯定缺少一些非常重要的方面。

Zah*_*yat 23

IOptionsMonitor是一个随时检索当前选项值的单例服务,这在单例依赖中特别有用。

IOptionsSnapshot是一个范围服务,并在构造对象时提供选项的快照IOptionsSnapshot<T>。选项快照旨在与瞬态作用域依赖项一起使用。

使用IOptions<T>时,你不希望你的配置值的变化。使用IOptionsSnaphot<T>时,你期待你的价值观改变,但希望它是一个请求的全部一致。使用 IOptionsMonitor<T>时,你需要真正的时间值。


Pau*_*ler 5

这些评论已经有一些不错的答案,可以尝试总结/重复Tseng。

IOptionsSnapshot非常适合注入作用域或瞬态的对象。这将与该对象的生存期保持一致,并且在获取新对象时会引入新的值。

但是,如果您需要在单例中重新加载的选项,则应该使用IOptionsMonitor,因为单例永远不会改变。从IHostedServiceAsp.net Core中长期运行的后台服务继承自的服务就是一个很好的例子。