在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
關鍵字: public configuration services