web-dev-qa-db-fra.com

Différence entre IOptionsMonitor et IOptionsSnapshot

Selon cette réponse , IOptionsMonitor est enregistré dans le conteneur DI en tant que singleton et est capable de détecter les changements via OnChange abonnement à un événement. Il possède une propriété CurrentValue.

D'autre part, IOptionsSnapshot est enregistré en tant que portée et a également une capacité de détection de changement en lisant les dernières options pour chaque demande, mais il n'a pas l'événement OnChange. Il possède une propriété Value.

Utiliser les deux injectés dans une vue, par exemple, nous donne exactement le même comportement:

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}";
        }
    }
}

Alors, quel est l'intérêt d'avoir ces deux interfaces/implémentations si elles ressemblent à la même chose, juste avec des durées de vie différentes? Le code est basé sur cet exemple , ce qui, étonnamment, n'inclut pas d'exemple d'utilisation IOptionsMonitor.

Pourquoi l'un a une propriété "Value" et l'autre a "CurrentValue" si les deux obtiennent la "valeur actuelle" d'une option?

Pourquoi/quand devrais-je utiliser IOptionsSnapshot au lieu de IOptionsMonitor?

Je ne pense pas avoir bien compris, je dois manquer un aspect très important concernant l'injection de ces dépendances.

12
natenho

Les commentaires ont déjà de très bonnes réponses pour essayer de résumer/répéter Tseng.

IOptionsSnapshot est idéal pour être injecté dans un objet de portée ou transitoire. Il sera cohérent avec la durée de vie de cet objet et de nouvelles valeurs entreront lorsque vous obtiendrez de nouveaux objets.

Cependant, si vous avez besoin d'options qui se rechargent dans un IOptionsMonitor singleton, c'est ce que vous devez utiliser car votre singleton ne changera jamais. Un bon exemple de tels services sont ceux hérités de IHostedService, pour les services d'arrière-plan de longue durée dans Asp.net Core.

2
Paul Miller