配置文件是应用程序的重要组成部分,它们使应用程序能够在不重新编译代码的情况下调整行为。在C#中,有多种方法可以读取和处理配置文件,本文将全面介绍这些技术及其最佳实践。
一、配置文件类型概述
1.1 常见配置文件格式对比
格式类型 | 文件扩展名 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
XML | .config, .xml | 结构清晰,支持复杂配置 | 冗长,可读性一般 | 传统.NET应用,WCF配置 |
JSON | .json | 轻量,易读,现代标准 | 缺乏注释(标准JSON) | ASP.NET Core,Web API |
INI | .ini | 简单易读 | 功能有限,无层次结构 | 简单桌面应用 |
YAML | .yaml, .yml | 人类友好,支持注释 | 缩进敏感,解析复杂 | Kubernetes,Docker |
环境变量 | – | 部署友好,安全 | 管理大量变量困难 | 容器化应用,云原生 |
二、XML配置读取(传统.NET方式)
2.1 App.config/Web.config基础
<!-- App.config示例 -->
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ApiEndpoint" value="https://api.example.com"/>
<add key="MaxRetries" value="3"/>
</appSettings>
<connectionStrings>
<add name="DefaultConnection"
connectionString="Server=.;Database=MyDB;Integrated Security=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
2.2 使用ConfigurationManager读取
using System.Configuration;
// 读取appSettings
string apiEndpoint = ConfigurationManager.AppSettings["ApiEndpoint"];
int maxRetries = int.Parse(ConfigurationManager.AppSettings["MaxRetries"]);
// 读取连接字符串
var connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
2.3 自定义配置节
<configuration>
<configSections>
<section name="customSettings" type="MyApp.CustomConfigurationSection, MyApp"/>
</configSections>
<customSettings>
<servers>
<add name="Primary" ip="192.168.1.1"/>
<add name="Secondary" ip="192.168.1.2"/>
</servers>
</customSettings>
</configuration>
public class CustomConfigurationSection : ConfigurationSection
{
[ConfigurationProperty("servers")]
public ServerCollection Servers => (ServerCollection)base["servers"];
}
public class ServerCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement() => new ServerElement();
protected override object GetElementKey(ConfigurationElement element) => ((ServerElement)element).Name;
}
public class ServerElement : ConfigurationElement
{
[ConfigurationProperty("name", IsKey = true, IsRequired = true)]
public string Name => (string)base["name"];
[ConfigurationProperty("ip", IsRequired = true)]
public string IP => (string)base["ip"];
}
// 使用
var config = (CustomConfigurationSection)ConfigurationManager.GetSection("customSettings");
foreach (ServerElement server in config.Servers)
{
Console.WriteLine($"{server.Name}: {server.IP}");
}
三、JSON配置读取(现代.NET方式)
3.1 appsettings.json基础
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=MyDB;Integrated Security=true"
},
"AppSettings": {
"ApiEndpoint": "https://api.example.com",
"MaxRetries": 3,
"Timeout": 30.5
}
}
3.2 ASP.NET Core配置系统
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 读取配置
string apiEndpoint = builder.Configuration["AppSettings:ApiEndpoint"];
int maxRetries = builder.Configuration.GetValue<int>("AppSettings:MaxRetries");
string connStr = builder.Configuration.GetConnectionString("DefaultConnection");
// 强类型绑定
var appSettings = builder.Configuration.GetSection("AppSettings").Get<AppSettings>();
public class AppSettings
{
public string ApiEndpoint { get; set; }
public int MaxRetries { get; set; }
public double Timeout { get; set; }
}
3.3 控制台应用中使用
using Microsoft.Extensions.Configuration;
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true)
.AddEnvironmentVariables()
.Build();
var settings = config.GetSection("AppSettings").Get<AppSettings>();
四、环境变量与多环境配置
4.1 多环境配置文件
appsettings.json
appsettings.Development.json
appsettings.Production.json
4.2 环境变量配置
# Linux/macOS
export AppSettings__ApiEndpoint="https://prod.api.example.com"
# Windows
set AppSettings__ApiEndpoint=https://prod.api.example.com
// 读取环境变量(冒号或双下划线)
var endpoint = builder.Configuration["AppSettings:ApiEndpoint"];
4.3 配置加载优先级
- 内存中的
KeyPerFile
配置 - 环境变量
- 用户机密(Development环境)
- appsettings.{Environment}.json
- appsettings.json
- 自定义配置提供程序
五、INI文件配置读取
5.1 INI文件示例
[Database]
Server=localhost
Port=5432
Username=admin
Password=secret
[Application]
LogLevel=Debug
MaxConnections=100
5.2 使用Windows API读取
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(
string section, string key, string def,
StringBuilder retVal, int size, string filePath);
public static string ReadIniValue(string filePath, string section, string key)
{
var sb = new StringBuilder(255);
GetPrivateProfileString(section, key, "", sb, 255, filePath);
return sb.ToString();
}
// 使用
string server = ReadIniValue("config.ini", "Database", "Server");
5.3 使用第三方库
dotnet add package IniFileParser
var parser = new IniFileParser.IniFileParser();
IniData data = parser.ReadFile("config.ini");
string username = data["Database"]["Username"];
int maxConn = int.Parse(data["Application"]["MaxConnections"]);
六、YAML配置读取
6.1 YAML示例
database:
server: "localhost"
port: 5432
credentials:
username: "admin"
password: "secret"
application:
log_level: "Debug"
features:
- "FeatureA"
- "FeatureB"
6.2 使用YamlDotNet
dotnet add package YamlDotNet
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
var yaml = File.ReadAllText("config.yml");
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var config = deserializer.Deserialize<AppConfig>(yaml);
public class AppConfig
{
public DatabaseConfig Database { get; set; }
public ApplicationConfig Application { get; set; }
}
public class DatabaseConfig
{
public string Server { get; set; }
public int Port { get; set; }
public Credentials Credentials { get; set; }
}
public class Credentials
{
public string Username { get; set; }
public string Password { get; set; }
}
七、配置变更监控与热重载
7.1 文件变更监控
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
// 注册变更回调
ChangeToken.OnChange(
() => config.GetReloadToken(),
() => Console.WriteLine("配置已更新: " + config["AppSettings:ApiEndpoint"]));
7.2 IOptions模式(ASP.NET Core)
// 注册服务
builder.Services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
// 控制器中使用
public class MyController : Controller
{
private readonly AppSettings _settings;
public MyController(IOptionsMonitor<AppSettings> settings)
{
_settings = settings.CurrentValue;
settings.OnChange(newSettings =>
{
_settings = newSettings;
});
}
}
八、安全最佳实践
- 敏感信息保护:
- 使用用户机密(Development):
bash dotnet user-secrets set "DbPassword" "s3cr3t"
- 生产环境使用Azure Key Vault或AWS Secrets Manager
- 配置文件权限:
- 限制配置文件访问权限
- 避免将配置文件提交到版本控制
- 连接字符串加密:
// 使用ProtectedConfigurationProvider
<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>...</EncryptedData>
</connectionStrings>
九、性能优化技巧
- 减少IO操作:
- 初始化时加载配置,避免重复读取
- 使用内存缓存配置数据
- 延迟加载:
private Lazy<AppSettings> _settings = new Lazy<AppSettings>(() =>
LoadConfig<AppSettings>("appsettings.json"));
- 选择高效解析器:
- 对于高性能场景,考虑使用System.Text.Json而非Newtonsoft.Json
十、自定义配置提供程序
10.1 实现IConfigurationProvider
public class MyCustomConfigProvider : ConfigurationProvider, IConfigurationSource
{
public override void Load()
{
// 从自定义源加载数据
Data["ApiSettings:Endpoint"] = "https://custom.source";
}
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return this;
}
}
// 注册
builder.Configuration.Add(new MyCustomConfigProvider());
10.2 数据库配置提供程序示例
public class DbConfigurationProvider : ConfigurationProvider
{
private readonly string _connectionString;
public DbConfigurationProvider(string connectionString)
{
_connectionString = connectionString;
}
public override void Load()
{
using var db = new SqlConnection(_connectionString);
var settings = db.Query<ConfigEntry>("SELECT Key, Value FROM Settings");
Data = settings.ToDictionary(
x => x.Key.Replace(':', ':'),
x => x.Value);
}
}
// 使用
builder.Configuration.Add(new DbConfigurationSource(connectionString));
十一、跨平台注意事项
- 路径处理:
// 使用Path.Combine而非硬编码路径
var configPath = Path.Combine(AppContext.BaseDirectory, "config", "settings.json");
- 大小写敏感:
- Linux文件系统区分大小写
- 环境变量命名规范保持一致
- 行尾符:
- 配置文件使用当前系统的行尾符
- Git可配置自动转换
十二、总结与建议
12.1 技术选型建议
应用类型 | 推荐配置方式 |
---|---|
传统.NET框架应用 | XML配置文件 + ConfigurationManager |
ASP.NET Core应用 | appsettings.json + IConfiguration |
控制台应用 | JSON/INI + 自定义加载 |
云原生应用 | 环境变量 + Key Vault集成 |
跨平台桌面应用 | JSON/YAML + 嵌入式资源 |
12.2 通用最佳实践
- 分层配置:基础配置(文件) + 环境特定配置(环境变量)
- 类型安全:使用强类型配置类而非直接访问字符串键
- 验证配置:启动时验证必要配置是否存在
- 文档化:为配置项添加说明和示例值
- 版本控制:配置文件应与代码版本同步
通过合理选择和实现配置读取策略,可以构建出既灵活又健壮的应用程序配置系统,满足从简单桌面应用到复杂云原生系统的各种需求。