.NET 應用程式設定儲存在 app.config (桌面應用) 或 web.config (ASP.NET) 的 <appSettings> 區段:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="IsInit" value="false" />
<add key="ApiEndpoint" value="https://api.example.com" />
<add key="MaxRetryCount" value="3" />
</appSettings>
</configuration>
System.Configuration.ConfigurationManager:靜態入口,讀取/開啟配置。System.Configuration.Configuration:可寫入的配置物件 (需 OpenExeConfiguration 取得)。KeyValueConfigurationCollection:AppSettings.Settings 集合操作介面。using System;
using System.Configuration;
namespace ConfigHelper
{
public static class AppConfig
{
///
/// 讀取設定值 (不存在回傳 null)
///
public static string Get(string key)
{
return ConfigurationManager.AppSettings[key];
}
///
/// 讀取設定值,帶預設值與型別轉換
///
public static T Get(string key, T defaultValue = default)
{
string val = ConfigurationManager.AppSettings[key];
if (val == null) return defaultValue;
try
{
// 支援基本型別、Enum、Guid、TimeSpan 等
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
return (T)converter.ConvertFromString(val);
}
catch
{
return defaultValue;
}
}
///
/// 寫入/更新設定值 (持久化到檔案)
///
public static void Set(string key, string value)
{
// 1. 開啟可寫入的配置物件 (當前執行檔層級)
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// 2. 修改或新增
var settings = config.AppSettings.Settings;
if (settings[key] == null)
settings.Add(key, value);
else
settings[key].Value = value;
// 3. 儲存 (Modified: 僅儲存變更區段)
config.Save(ConfigurationSaveMode.Modified);
// 4. 強制重新整理快取,後續 Get 立即生效
ConfigurationManager.RefreshSection("appSettings");
}
///
/// 批次寫入 (單次儲存,效能更好)
///
public static void SetBatch(IDictionary keyValues)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var settings = config.AppSettings.Settings;
foreach (var kv in keyValues)
{
if (settings[kv.Key] == null)
settings.Add(kv.Key, kv.Value);
else
settings[kv.Key].Value = kv.Value;
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
///
/// 刪除設定
///
public static void Remove(string key)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings[key] != null)
{
config.AppSettings.Settings.Remove(key);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}
}
}
}
// 讀取字串
string endpoint = AppConfig.Get("ApiEndpoint");
// 讀取整數 (帶預設值)
int maxRetry = AppConfig.Get("MaxRetryCount", 3);
// 讀取布林
bool isInit = AppConfig.Get("IsInit", false);
// 寫入單值
AppConfig.Set("IsInit", "true");
AppConfig.Set("LastLogin", DateTime.Now.ToString("o"));
// 批次寫入 (應用啟動時初始化多項設定)
AppConfig.SetBatch(new Dictionary
{
{ "WindowWidth", "1200" },
{ "WindowHeight", "800" },
{ "Theme", "Dark" }
});
// 刪除
AppConfig.Remove("ObsoleteKey");
| 主題 | 說明 | 最佳實踐 |
|---|---|---|
| 作用域層級 | ConfigurationUserLevel.None = 應用程式層級 (exe.config)PerUserRoamingAndLocal = 使用者層級 (user.config) |
桌面應用通常用 None;需使用者個人化設定時用 PerUser |
| Web.config 特殊性 | ASP.NET 執行於 IIS 背景進程,OpenExeConfiguration 需指定實體路徑 |
Web 環境建議改用 WebConfigurationManager 或直接操作 ConfigurationManager (IIS 7+ 整合模式自動映射) |
| 執行時修改不生效 | 未呼叫 RefreshSection 或快取未失效 |
寫入後必呼叫 ConfigurationManager.RefreshSection("appSettings") |
| 權限問題 | 寫入 Program Files 下的 exe.config 需管理員權限 |
生產環境將可寫入設定移至 user.config 或 AppData 目錄自訂 JSON/XML |
| 加密敏感值 | 連線字串、API Key 不應明文 | 使用 config.SectionInformation.ProtectSection("DataProtectionConfigurationProvider") 或外部 Vault |
| 強型別設定類別 | 大型專案建議定義 ConfigurationSection 衍生類別 |
獲得 IntelliSense、編譯期檢查、預設值、驗證邏輯 |
using System.Configuration;
public class AppSettingsSection : ConfigurationSection
{
[ConfigurationProperty("isInit", DefaultValue = false, IsRequired = true)]
public bool IsInit
{
get => (bool)this["isInit"];
set => this["isInit"] = value;
}
[ConfigurationProperty("apiEndpoint", DefaultValue = "https://api.default.com", IsRequired = true)]
[RegexStringValidator(@"^https?://.+")]
public string ApiEndpoint
{
get => (string)this["apiEndpoint"];
set => this["apiEndpoint"] = value;
}
[ConfigurationProperty("maxRetry", DefaultValue = 3, IsRequired = false)]
[IntegerValidator(MinValue = 0, MaxValue = 10)]
public int MaxRetry
{
get => (int)this["maxRetry"];
set => this["maxRetry"] = value;
}
}
// 註冊於 config 檔:
// <configSections>
// <section name="myApp" type="Namespace.AppSettingsSection, AssemblyName" />
// </configSections>
// <myApp isInit="false" apiEndpoint="https://api.example.com" maxRetry="3" />
// 使用:
var section = (AppSettingsSection)ConfigurationManager.GetSection("myApp");
bool init = section.IsInit; // 強型別、自動驗證
新專案強烈建議使用 JSON 配置 + 選項模式:
// appsettings.json
{
"AppSettings": {
"IsInit": false,
"ApiEndpoint": "https://api.example.com",
"MaxRetryCount": 3
}
}
// 註冊 (Program.cs / Startup.cs)
builder.Services.Configure(builder.Configuration.GetSection("AppSettings"));
// 注入使用
public class MyService
{
private readonly AppSettings _settings;
public MyService(IOptions options) => _settings = options.Value;
public void DoWork() => Console.WriteLine(_settings.ApiEndpoint);
}
// 熱更新支援
builder.Services.Configure(builder.Configuration.GetSection("AppSettings"));
// 配合 IOptionsMonitor 或 IOptionsSnapshot
ConfigurationManager 是 .NET Framework 經典配置存取 API,雖然 API 略顯繁瑣,但掌握 OpenExeConfiguration → 修改 Settings → Save(Modified) → RefreshSection 這四步核心流程,即能應付絕大多數讀寫需求。新專案請優先擁抱 appsettings.json + IOptions,享受強型別、依賴注入、熱更新、環境區隔 (Development/Staging/Production) 等現代化配置體驗。