提要
- DI Configuration
- 組態的層次
- Options Pattern
DI Configuration
dotnet webapi 專案預設會注入 IConfiguration ,
在專案中的程式建構子放入 IConfiguration
就可以直接取得組態設定
1 | private readonly IConfiguration _config; |
你可以將組態設定在 appsettings.json
之中
或是透過環境變數,使用環境變數有幾種作法
- 設定在機器上
- 設定在 Cloud Service 所提供的組態管理工具之中
- 使用
launchSettings.json
在開發環境我會使用 launchSettings
好處是可以不需要真的在開發機的環境中設定環境變數,
對同時擁有多個專案的開發者而言,可以有效隔離不同的專案變數,避免彼此影響污染
組態的層次
為了方便管理,我們可以透過組態的層次來加以分門別類。
比如說:
1 | "Level": { |
一般的 JSON 或 XML 要作到這樣的層次結構都相當的簡單,
而要取用組態的方式如下:
1 | var key = _config["Level:First:Key"]; |
不過我們要注意環境變數並無法使用:
字符,也沒有 JSON 或是 XML 所能提供的結構,
這裡要注意可以用 __(雙底線(Double underscore))來建立層次。
1 | $Level__First__Key |
Options Pattern
Options Pattern 可以提供一種更物件導向的組態配置解決方案,
你只需要兩個步驟,即可實作 Options Pattern
建立 Option 物件
我在這裡提供二種不同的方法,後面會再說明1
2
3
4
5
6//方法一 Dictionary
public class LevelOptions
{
public const string Level = "Level";
public Dictionary<string,string> First { get; set; }1
2
3
4
5
6
7
8
9
10
11
12//方法二 Object
public class LevelOption
{
public const string Level = "Level";
public FirstOptions First { get; set; }
}
public class FirstOptions
{
public string Key { get; set; } = string.Empty;
}註冊 Option 物件
1 | builder.Services.Configure<LevelOptions>(LevelOption.Level) |
最後是讀取組態,在方法一(使用 Dictionary)的方法讀取
1 | var key = _options.Value.First["Key"]; |
或是方法二(使用 Object)的方法讀取
1 | var key = _options.Value.First.Key; |
兩種方法都可以,物件化的方法需要建立多個物件,
但是在取用組態的過程就不會有 hard coding string;
反之 Dictionary 的方法可以少寫很多物件。
對我而言我比較偏向使用 Object 的方法去處理,只要適當的分類,
物件多並不是問題,而且通常一次不會增加太多的組態,可以迭代增量。
順代一提,如果組態檔層次太多,會是另一個困擾 ? 我的建議是,如果組態的深度到達 3 時,
需要考慮這是不是一個壞味道,是不是過度優化了 ?
實務上來說,我會避免建立超過 3 層,也很難會有一定要超過 3 層的情境,
如果你有什麼情境上需要超過 3 層,可以留言給我,我們可以一起討論。
在 Program.cs 使用
如果在 Program.cs
的注入階段,如果要取得組態,
可以用(new ConfigurationManager()).GetSection("First")["Key"]
或是 Environment.GetEnvironmentVariable("Level__First__Key");
等方法取得組態。
但是我更推薦 ServiceProvider 的 GetRequiredService 取得 Options
1 | //注入在前 |
這樣就可以用一致的方法取得組態了。
參考
- ASP.NET Core 的設定
- ASP.NET Core 中的選項模式
- .NET 中的選項模式
- Looking inside ConfigurationManager in .NET 6
- 你可能不知道的.Net Core Configuration(Evernote 備份)
(fin)