ASP.NET Core筆記(4) - 選項模式

  • 選項接口
  • IOptionsSnapshot與IOptionsMonitor的區別
  • 選項的後期配置
  • 選項的驗證
  • 在ASP.NET Core筆記(3) - 配置中介紹了各種配置提供程序以及配置的讀取方式,但實際使用中,不推薦應用程序直接從一堆配置中讀取的做法,而是使用強類型綁定,將配置按組綁定到不同服務所屬的類。使用這種方式可以讓配置方案遵守兩個重要的軟件工程原則:

    • 接口分離原則 (ISP) 或封裝 – 依賴於配置設置的方案(類)僅依賴於其使用的配置設置。
    • 關注點分離 – 應用的不同部件的設置不彼此依賴或相互耦合。

    選項接口

    ASP.NET Core選項模式常用的接口有

    • IOptions
    • IOptionsSnapshot
    • IOptionsMonitor

    IOptions在配置更改時無法對應變更選項的值,只能重啟應用。IOptionsSnapshot和IOptionsMonitor則具有這種能力。

    選項可以作為服務在使用時被注入,下面的代碼模擬了選項的使用場景,OrderServiceOptions作為OrderService的選項被注入,OrderService又在控制器中被注入:

    <code>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; };
    }
    /<code>

    控制器中注入OrderService:

    <code>[HttpGet]
    public string Get([FromServices]IOrderService orderService)
    {
        var res = $"orderService.ShowMaxOrderCount:{orderService.ShowMaxOrderCount()},time={orderService.ShowTime()}";
        Console.WriteLine(res);
        return res;
    }
    /<code>

    在ConfigService配置OrderServiceOptions和OrderService的注入:

    <code>services.Configure(Configuration.GetSection("OrderService"));
    services.AddScoped();
    /<code>

    IOptionsSnapshot與IOptionsMonitor的區別

    這裡注入時使用的是AddScoped作用域的方式,是因為使用了IOptionsSnapshot接口。IOptionsSnapshot的生命週期為作用域,會在每次請求時應重新讀取配置、更新選項。所以修改配置後,重新請求API,就可以看到最新的配置值。如果嘗試選擇AddSingleton,由於OrderService單例的生命週期比IOptionsSnapshot更長,會直接拋出運行時異常。

    而如果遇到既需要單例生命週期,還需要變更檢測的場景時怎麼辦呢?這時就需要用到IOptionsMonitor了。IOptionsMonitor 和 IOptionsSnapshot 之間的區別在於:

    • IOptionsMonitor 是一種單例服務,且可以監測配置的變更。
    • IOptionsSnapshot 是一種作用域服務,並在構造 IOptionsSnapshot 對象時提供選項的快照。

    IOptionsMonitor使用與IOptionsSnapshot類似,但取值變為CurrentValue。如果修改配置源,就會觸發OnChange方法:

    <code>_options.OnChange(option =>
    {
        Console.WriteLine($"配置更新了,最新的值是:{_options.CurrentValue.MaxOrderCount}");
    });
    /<code> 

    IOptionsMonitor還可以結合ASP.NET Core筆記(3) - 配置中介紹的自定義數據源的方法,當IConfigurationProvider觸發OnReload()事件時,這裡的OnChange也就會被觸發。

    選項的後期配置

    使用PostConfigure可進行選項的後期配置:

    <code>services.PostConfigure(options =>
    {
        options.MaxOrderCount += 20;
    });
    /<code>

    選項的驗證

    為了防止應用程序讀取到錯誤的配置,可以為選項添加驗證。選項驗證有三種方式:

    • 直接註冊驗證函數
    • DataAnnotations
    • 實現IValidateOptions接口

    直接註冊驗證函數

    添加選項需要替換為AddOptions

    <code>//services.Configure(configuration);
    services.AddOptions().Bind(configuration).Configure(options =>
    {
    configuration.Bind(options);
    })
    .Validate(options => options.MaxOrderCount <= 100, "MaxOrderCount不能大於100");
    /<code>

    DataAnnotations

    調用ValidateDataAnnotations:

    <code>services.AddOptions().Bind(configuration).Configure(options =>
    {
    configuration.Bind(options);
    })
    .ValidateDataAnnotations();
    /<code>

    為選項模型類添加Annotation:

    <code>public class OrderServiceOptions
    {
        [Range(0, 100)]
        public int MaxOrderCount { get; set; };
    }
    /<code>

    實現IValidateOptions接口

    註冊驗證服務:

    <code>services.AddOptions().Bind(configuration).Configure(options =>
    {
    configuration.Bind(options);
    })
    .Services.AddSingleton,OrderServiceValidateOptions> ();
    /<code>

    實現IValidateOptions:

    <code>public class OrderServiceValidateOptions : IValidateOptions
    {
        public ValidateOptionsResult Validate(string name, OrderServiceOptions options)
        {
            if (options.MaxOrderCount > 100)
            {
                return ValidateOptionsResult.Fail("MaxOrderCount不能大於100");
            }
            else
            {
                return ValidateOptionsResult.Success;
            }
        }
    }
    /<code>

    原文地址;https://www.cnblogs.com/zhixin9001/p/12708713.html


    分享到:


    相關文章: