首页 > 解决方案 > IOptionsMonitor 与 IOptionsSnapshot 之间的区别

问题描述

根据这个答案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}";
        }
    }
}

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

如果两者都返回选项的“当前值”,为什么一个具有“值”属性而另一个具有“当前值”?

为什么/何时应该使用IOptionsSnapshot而不是IOptionsMonitor

我不认为我说得通,我一定遗漏了一些关于这些和依赖注入的非常重要的方面。

标签: asp.net-coredependency-injectioninterfaceoptionsobject-lifetime

解决方案


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

IOptionsSnapshot是一个范围服务,并在构造对象时提供选项的快照。IOptionsSnapshot<T>选项快照设计用于瞬态范围依赖项。

IOptions<T>当您不希望配置值更改时使用。IOptionsSnaphot<T>当您期望您的值发生变化但希望它在整个请求中保持一致时使用。IOptionsMonitor<T>当您需要实时值时使用 。


推荐阅读