之前在
C# 設定檔教學 (三) 最方便的 Json設定檔
這篇中有介紹到讀取 JSON 的設定檔,那時是使用最簡單的方式,直接讀取文字檔案,然後反序列化為物件讀取。
不過其實會有個小問題,就是各類型的設定值無法拆分,不管是什麼功能(模組)的設定值都需要維護同一個 class ,耦合性很高,其實我們可以使用和 ASP.NET Core 一樣的方式,有個「設定值提供者」來負責主要的讀取,要使用這種方式很容易,只要安裝微軟的套件即可。
另外還需要安裝 Microsoft.Extensions.Configuration.Binder 套件,用來自動將設定值的鍵值對資料反序列化為物件
建立兩個類別用來處理設定值:
這裡示範只有最基礎的 string 型別,但其實 int, List 等都是可以的。
就可以很簡單的讀取設定值了:
註: 上面的 Directory.GetCurrentDirectory() 是設定讀取 appsettings.json 的路徑為專案執行路徑,這樣在哪裡使用 dotnet run 就會讀取該資料夾下的 appsettings.json 檔案,也可以自行變更。
不過如果會需要寫回設定值,那我們只能自己實現將不同功能(模組)的設定值寫回,不過這個套件其實可以讀取多個設定檔,並依照優先順序決定要套用哪一個值,但是在寫回時我們沒有辦法簡單的分辨,只能都寫到其中一個設定檔中,這點需要注意。
下面是筆者寫的簡單實現:
這樣假設 Module2Options 的內容更新後要儲存時就可以這樣使用:
安裝
先使用 NuGet 安裝 Microsoft.Extensions.Configuration.Json 套件,或是使用 .NET CLI 執行以下指令安裝
dotnet add package Microsoft.Extensions.Configuration.Json
另外還需要安裝 Microsoft.Extensions.Configuration.Binder 套件,用來自動將設定值的鍵值對資料反序列化為物件
dotnet add package Microsoft.Extensions.Configuration.Binder
讀取設定檔
我們建立一個 appsettings.json 檔案,用來放置設定檔內容,範例設定值如下:
{
"Module1": {
"Key1": "Value1"
},
"Module2": {
"Key2": "Value2"
}
}
建立兩個類別用來處理設定值:
public class Module1Options
{
public string Key1 { get; set; }
}
public class Module2Options
{
public string Key2 { get; set; } = null!;
}
這裡示範只有最基礎的 string 型別,但其實 int, List 等都是可以的。
就可以很簡單的讀取設定值了:
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()) // 設定基本路徑為目前專案的目錄
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
Module1Options? module1Options = configuration.GetSection("Module1").Get<Module1Options>();
if(module1Options == null) throw new Exception("設定檔讀取錯誤,找不到 Module1 設定");
Console.WriteLine($"Key1: {module1Options.Key1}");
Module2Options? module2Options = configuration.GetSection("Module2").Get<Module2Options>();
if(module2Options == null) throw new Exception("設定檔讀取錯誤,找不到 Module2 設定");
Console.WriteLine($"Key2: {module2Options.Key2}");
註: 上面的 Directory.GetCurrentDirectory() 是設定讀取 appsettings.json 的路徑為專案執行路徑,這樣在哪裡使用 dotnet run 就會讀取該資料夾下的 appsettings.json 檔案,也可以自行變更。
儲存設定值
尷尬的來了,在 ASP.NET Core 的設定中並不需要儲存設定值,所以在我們剛剛安裝的套件中並沒有這個功能。不過如果會需要寫回設定值,那我們只能自己實現將不同功能(模組)的設定值寫回,不過這個套件其實可以讀取多個設定檔,並依照優先順序決定要套用哪一個值,但是在寫回時我們沒有辦法簡單的分辨,只能都寫到其中一個設定檔中,這點需要注意。
下面是筆者寫的簡單實現:
void SaveConfiguration(string configName, object newOptions)
{
const string configPath = "appsettings.json";
var jsonSerializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string json = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), configPath));
var jsonObject = JsonDocument.Parse(json).RootElement.Clone();
// 將修改後的設定值寫入 JSON 物件
using (var stream = new MemoryStream())
{
using (var writer = new Utf8JsonWriter(stream))
{
jsonObject.WriteTo(writer);
}
var modifiedJson = JsonSerializer.Deserialize<Dictionary<string, object>>(stream.ToArray());
if (modifiedJson == null) throw new Exception("設定檔讀取錯誤");
modifiedJson[configName] = newOptions; // 更新部分設定
string updatedJson = JsonSerializer.Serialize(modifiedJson, jsonSerializerOptions);
File.WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), configPath), updatedJson);
}
}
這樣假設 Module2Options 的內容更新後要儲存時就可以這樣使用:
module2Options.Key2 = "新的值123";
SaveConfiguration("Module2", module2Options);
感謝教學~
回覆刪除