本篇只是從應用角度來說明asp.net core的選項模式,下一篇會從源碼來分析 1、以前的方式 以前我們使用web.config/app.config時是這樣使用配置的 寫["key"]操作麻煩,弱類型的還得自己轉,後來有人做了封裝 稍微好了點,全能方式,系統任何地方都可以調用,但是沒有組織,最好 ...
本篇只是從應用角度來說明asp.net core的選項模式,下一篇會從源碼來分析
1、以前的方式
以前我們使用web.config/app.config時是這樣使用配置的
var count = ConfigurationManager.AppSettings["key"];
寫["key"]操作麻煩,弱類型的還得自己轉,後來有人做了封裝
public static class ConfigHelper{ public static T Get<T>(string key){ return (T)ConfigurationManager.AppSettings[key]; }
}
稍微好了點,全能方式,系統任何地方都可以調用,但是沒有組織,最好是為單獨的模塊定義一個類,比如為訂單模塊定義一個配置類
public static class OrderConfig{ public static int Opt1{
get{ return ConfigHelper.Get<int>("opt1"); }
}
}
這時我們在訂單業務中隨時都可以訪問這個配置,且是強類型的
2、asp.net core中的選項模式
asp.net core中把這種為小模塊定義的配置類稱為選項模式,我們把這個配置對象稱為選項對象.微軟為我們定義了一些類,這些類相互協作完成了以下任務:
1、配置來源可以是記憶體數據、xml、json、ini文件、資料庫...或其它,也要支持我們自定義的來源
2、配置文件發生更改後配置對象自動更新
3、我們希望自己控制配置的生命周期,比如:
我希望拿到的這個選項對象在應用程式運行期間永遠不變
我希望每次請求拿到的選項對象都是最新的,意思說每次請求你都幫我根據配置源重新創建一個選項對象
我希望首先根據源創建選項對象,並且一直緩存它,當源有變化時幫我刷新配置對象
先做個說明:可能你有瞭解過asp.net core中的配置,其實選項與配置沒有必然的聯繫,因為選項模式的根本是體現為單獨的模塊定義一個配置對象,方便訪問,至於這個配置對象的數據從哪來則不規定,你可以使用任何方式,但是使用asp.net core提供的配置功能更方便也更常見而已
再者選項模式跟依賴註入也沒有必然的聯繫,原因跟上面一樣,但是asp.net core提供的選項模式是建立在依賴註入基礎上的。但又與我們通常理解的有所不同。通常我們是定義介面IA,實現類A,然後註冊iocContainer.Register<IA,A>(); 然後在使用時通過構造函數或屬性註入。所以你可能會認為我們為某個模塊定義選項時需要定義一個選項類,再定義一個對應的什麼介面。其實不需要,因為asp.net core為我們提供了相應的泛型類,具體的看下麵部分的說明來理解
下麵我們假設我們在做一個類似網盤的功能模塊,它涉及到一些配置,允許上傳的文件尾碼列表、單次上傳允許的文件的大小
2.1、定義選項類
public class CloudDiskOption{ public string AllowFileTypes{ get; set; }
public int AllowSize { get; set; }
}
2.2、定義選項對象如何賦值
asp.net core允許我們自己來定義選項對象如何賦值,最簡單的方式是使用委托,代碼如下
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CloudDiskOption>(c=> {
c.AllowSize = 1024;
c.AllowFileTypes = "jpg,zip,pdf,docx";
});
services.AddControllersWithViews();
}
這樣將來我們在需要使用選項類時asp.net core的選項框架會使用這個委托來幫我們創建
但更常見的方式是使用asp.net core提供的配置
西安在appsettings.json中做如下配置:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"myoption": {
"allowFileTypes": "jpg,zip,pdf,docx",
"allowSize": "1024"
}
}
你會看到我故意將選項類名與這裡的配置鍵myoption設置成不一樣,且配置項的大小寫也不對應,這些屬於配置部分的內容,這裡不多講,下麵修改我們的Startup類
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CloudDiskOption>(Configuration.GetSection("myoption"));
services.AddControllersWithViews();
}
這樣將來我們需要選項對象時系統會通過配置來創建選項對象
2.3、使用選項對象
通常我們使用以來註入來獲取選項對象,asp.net core為我們提供了幾個泛型介面,個人理解的基本原則如下
- 當你的選項對象基本不變時使用IOptions<TOptions> ,它會一直緩存選項對象,可以理解為單例選項對象
- 當你希望每個請求都重讀配置以獲得新的選項對象時使用IOptionsSnapshot<TOptions>
- 當你希望一直緩存我的選項對象,但當配置源發生更改時自動更新我的選項對象時使用IOptionsMonitor<TOptions>
網上有些文章說IOptionsMonitor<TOptions>是使用得最少的,我反而覺得它應該是最常用的
另外它有個OnChange可以註冊一個委托,就是當選項更改後你希望做啥,看情況應該小心使用,因為它可能會導致你的調用方的對象一直無法釋放,但是我想微軟不會太傻,應該有個釋放機制,目前那裡的源碼沒看太懂
下麵我們來看咋用,比如我們希望在controller中訪問選項,通過構造函數註入
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
CloudDiskOption myOption;
public HomeController(ILogger<HomeController> logger, IOptionsMonitor<CloudDiskOption> optionsMonitor)
{
_logger = logger;
optionsMonitor.OnChange((a,b)=>
{
//危險
});
this.myOption = optionsMonitor.CurrentValue;
}
這是你的controller對象的其他action就可以隨便訪問myOption了,可以嘗試修改配置文件後觀察變化
其它兩個介面用法類似,不在敘述
3、總結
從應用的角度來講選項用起來還是非常簡單方便的,兩個步驟:1定義選項的如何賦值 2使用的地方通過相應的泛型介面註入
下一篇會從源碼來分析asp.net core選項框架原理