配置选项(Options)
本页系统性介绍 Ape‑Volo‑Admin 中“配置选项”的注册与使用,包括:
- Options 模式与自动注册机制
OptionsSettingsAttribute的作用与路径映射GlobalType.CoreTypes的反射扫描来源- 如何声明 Options 类型、编写配置、在代码中注入使用
- 常见问题与最佳实践
总览
运行机制
在启动时,框架会通过 GlobalType.CoreTypes 反射获取指定程序集中的所有类型,筛选出标注了 OptionsSettingsAttribute 的类型,并统一调用 services.AddConfigurableOptions(type) 完成注册与配置绑定。
关键点:
- 所有带有
OptionsSettingsAttribute的类都会被自动注册为可注入的 Options。 - 如果特性携带
Path,将以该路径从配置文件(如appsettings*.json)进行绑定;未指定时由注册扩展推断或使用类型名作为默认节。 - 默认支持多环境配置文件覆盖(如
appsettings.Development.json)。
源码位置与工作原理
注册扩展(节选)
csharp
/// <summary>
/// 可配置选项扩展
/// </summary>
public static class OptionRegisterExtensions
{
/// <summary>
/// 注册配置选项
/// </summary>
public static void AddOptionRegisterService(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
var optionTypes = GlobalType.CoreTypes
.Where(x => x.GetCustomAttribute<OptionsSettingsAttribute>() != null)
.ToList();
foreach (var optionType in optionTypes)
{
services.AddConfigurableOptions(optionType);
}
}
}说明:
GlobalType.CoreTypes:通过反射收集了目标项目(通常为 Core/Infrastructure 等核心项目)中的所有类型集合。OptionsSettingsAttribute:标记“哪些类型是配置项”;可选的Path指定在配置文件中的绑定节路径。AddConfigurableOptions:将类型与配置绑定为可注入的 Options(相当于services.Configure<T>(Configuration.GetSection(path))的增强封装)。
特性定义(节选)
csharp
[AttributeUsage(AttributeTargets.Class)]
public class OptionsSettingsAttribute : Attribute
{
public OptionsSettingsAttribute() { }
/// <param name="path">appsettings.json 对应键</param>
public OptionsSettingsAttribute(string path)
{
Path = path;
}
/// <summary>
/// 对应配置文件中的路径
/// </summary>
public string Path { get; set; }
}如何新增一个 Options
- 声明一个选项类型并添加特性:
csharp
[OptionsSettings("System")]
public class SystemOptions
{
public bool UseRedisCache { get; set; } = false;
}- 在配置文件中添加对应节(示例
appsettings.Development.json):
json
{
"System": {
"UseRedisCache": true
}
}- 启动时调用注册扩展(通常在应用启动模块或 Startup/Program 中):
csharp
services.AddOptionRegisterService();- 在代码中使用(三种常见方式):
csharp
// 方式 A:静态帮助类(项目内常见用法)
var useRedis = App.GetOptions<SystemOptions>().UseRedisCache;
// 方式 B:通过 IOptions<T>(单例/启动期读取)
public class Foo
{
public Foo(IOptions<SystemOptions> options)
{
var useRedis = options.Value.UseRedisCache;
}
}
// 方式 C:IOptionsSnapshot<T>(每次请求最新,适合 Web 场景)
public class Bar
{
public Bar(IOptionsSnapshot<SystemOptions> options)
{
var useRedis = options.Value.UseRedisCache;
}
}更多示例
Redis 配置
csharp
[OptionsSettings("Redis")]
public class RedisOptions
{
public string Host { get; set; }
public int Port { get; set; } = 6379;
public string Password { get; set; }
public int Index { get; set; } = 0;
public int ConnectTimeout { get; set; } = 10000;
}json
{
"Redis": {
"Host": "localhost",
"Port": 6379,
"Password": "",
"Index": 0,
"ConnectTimeout": 10000
}
}中间件配置(片段)
csharp
[OptionsSettings("Middleware")]
public class MiddlewareOptions
{
public IpLimitOptions IpLimit { get; set; } = new();
}
public class IpLimitOptions
{
public bool Enabled { get; set; } = true;
}json
{
"Middleware": {
"IpLimit": { "Enabled": true }
}
}最佳实践
- 推荐将本地开发配置放在
appsettings.Development.json,避免污染生产配置。 - 为 Options 属性设置健壮的默认值,减少缺失配置导致的异常。
- 命名与路径要简洁一致:
[OptionsSettings("System")]对应"System": { ... }。 - 配置发生变更且需要热更新时,优先使用
IOptionsSnapshot<T>(Web 场景)或IOptionsMonitor<T>。 - 对关键选项加入校验(可结合数据注解或自定义 Validate),在启动期尽早失败。
- 新增 Options 类型时,确保其所在程序集被
GlobalType.CoreTypes覆盖到。
常见问题(FAQ)
- 新增的 Options 未生效?
- 是否添加了
OptionsSettingsAttribute特性; - 是否在
GlobalType.CoreTypes的扫描范围内; - 是否调用了
services.AddOptionRegisterService(); - 配置文件路径与特性 Path 是否一致(大小写/层级)。
- 是否添加了
- 多环境下覆盖无效?
- 确认当前环境(ASPNETCORE_ENVIRONMENT)与对应的
appsettings.{Env}.json已加载; - 冲突项是否被更下游的配置源覆盖(例如环境变量/命令行)。
- 确认当前环境(ASPNETCORE_ENVIRONMENT)与对应的
- 如何在非 Web 场景读取最新配置?
- 使用
IOptionsMonitor<T>或在自定义配置变更回调中刷新内部状态。
- 使用
相关联页面
- 《缓存》:示例中使用
SystemOptions.UseRedisCache切换缓存实现。 - 《IP 限流》:示例中使用
MiddlewareOptions.IpLimit.Enabled控制中间件启停。

