ASP.NET Coreノート(4)-オプションモード

4849 ワード

  • オプションインタフェース
  • IOptionsSnapshotとIOptionsMonitorの違い
  • オプションの後期構成
  • オプションの検証
  • ASP.NET Coreノート(3)-構成では様々な構成プロバイダおよび構成の読み取り方が紹介されていますが、実際の使用では、アプリケーションが直接構成の山から読み取るのではなく、強いタイプのバインドを使用して、構成をグループ別に異なるサービスが属するクラスにバインドすることをお勧めします.この方法を使用すると、構成スキームは2つの重要なソフトウェアエンジニアリングの原則を遵守できます.
  • インタフェース分離の原則(ISP)またはパッケージ–構成設定に依存するスキーマ(クラス)は、使用する構成設定にのみ依存します.
  • 注目点分離–適用される異なる構成要素の設定は、互いに依存したり結合したりしない.

  • オプションインタフェース
    ASP.NET Coreオプションモードでよく使われるインタフェースは
  • IOptions
  • IOptionsSnapshot
  • IOptionsMonitor

  • IOptionsは、構成変更時に変更オプションの値に対応できず、適用のみを再起動できます.IOptionsSnapshotとIOptionsMonitorはこの能力を持っている.
    オプションはサービスとして使用できます.次のコードはオプションの使用シーンをシミュレートし、OrderServiceOptionsはOrderServiceのオプションとして注入され、OrderServiceはコントローラに注入されます.
    public interface IOrderService
    {
        int ShowMaxOrderCount();
    }
    
    public class OrderService : IOrderService
    {
        IOptionsSnapshot _options;
        public OrderService(IOptionsSnapshot options)
        {
            _options = options;
        }
    
        public int ShowMaxOrderCount()
        {
            return _options.Value.MaxOrderCount;
        }
    }
    
    public class OrderServiceOptions
    {
        public int MaxOrderCount { get; set; };
    }
    

    コントローラにOrderServiceを注入するには:
    [HttpGet]
    public string Get([FromServices]IOrderService orderService)
    {
        var res = $"orderService.ShowMaxOrderCount:{orderService.ShowMaxOrderCount()},time={orderService.ShowTime()}";
        Console.WriteLine(res);
        return res;
    }
    

    コンフィグサービスでOrderServiceOptionsとOrderServicesのインジェクションを構成するには、次の手順に従います.
    services.Configure(Configuration.GetSection("OrderService"));
    services.AddScoped();
    

    IOptionsSnapshotとIOptionsMonitorの違い
    ここで注入時にAddScopedスコープ方式を用いたのは,IOptionsSnapshotインタフェースを用いたためである.OptionsSnapshotのライフサイクルは役割ドメインであり、リクエストのたびに構成、更新オプションを再読み込みする必要があります.したがって、構成を変更した後、APIを再要求すると、最新の構成値が表示されます.AddSingletonを選択しようとすると、OrderServiceの一例のライフサイクルがIOptionsSnapshotよりも長いため、ランタイム異常が直接放出されます.
    単一のライフサイクルが必要で、検出を変更するシーンが必要な場合はどうすればいいのでしょうか.この場合、IOptionsMonitorを使う必要があります.OptionsMonitorとOptionsSnapshotの違いは次のとおりです.
  • IOptionsMonitorは、構成の変更を監視できる単一のサービスです.
  • IOptionsSnapshotは、アクティブドメインサービスであり、IOptionsSnapshotオブジェクトを構築するときにオプションのスナップショットを提供します.

  • OptionsMonitorは、OptionsSnapshotと同様に使用されますが、CurrentValueになります.構成ソースを変更すると、OnChangeメソッドがトリガーされます.
    _options.OnChange(option =>
    {
        Console.WriteLine($"     ,     :{_options.CurrentValue.MaxOrderCount}");
    });
    

    OptionsMonitorはASP.と組み合わせることもできます.NET Coreノート(3)-構成で紹介されているカスタムデータソースの方法は、IConfigurationProviderがOnReload()イベントをトリガーすると、ここのOnChangeもトリガーされます.
    オプションのポスト設定
    PostConfigureを使用して、オプションの後期構成を行います.
    services.PostConfigure(options =>
    {
        options.MaxOrderCount += 20;
    });
    

    オプションの検証
    アプリケーションが誤った構成に読み込まれないように、オプションに検証を追加できます.オプション検証には、次の3つの方法があります.
  • 直接登録検証関数
  • DataAnnotations
  • IValidateOptionsインタフェース
  • を実装
    直接登録検証関数
    オプションを追加するにはAddOptionsに置き換える必要があります
    //services.Configure(configuration);
    services.AddOptions().Bind(configuration).Configure(options =>
    {
    configuration.Bind(options);
    })
    .Validate(options => options.MaxOrderCount <= 100, "MaxOrderCount    100");
    

    DataAnnotations
    ValidateDataAnnotationsを呼び出します.
    services.AddOptions().Bind(configuration).Configure(options =>
    {
    configuration.Bind(options);
    })
    .ValidateDataAnnotations();
    

    オプションモデルクラスにAnnotationを追加するには:
    public class OrderServiceOptions
    {
        [Range(0, 100)]
        public int MaxOrderCount { get; set; };
    }
    

    IValidateOptionsインタフェースの実装
    認証サービスの登録:
    services.AddOptions().Bind(configuration).Configure(options =>
    {
    configuration.Bind(options);
    })
    .Services.AddSingleton,OrderServiceValidateOptions> ();
    

    IValidateOptionsの実装:
    public class OrderServiceValidateOptions : IValidateOptions
    {
        public ValidateOptionsResult Validate(string name, OrderServiceOptions options)
        {
            if (options.MaxOrderCount > 100)
            {
                return ValidateOptionsResult.Fail("MaxOrderCount    100");
            }
            else
            {
                return ValidateOptionsResult.Success;
            }
        }
    }