Skip to content

配置选项(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

  1. 声明一个选项类型并添加特性:
csharp
[OptionsSettings("System")]
public class SystemOptions
{
    public bool UseRedisCache { get; set; } = false;
}
  1. 在配置文件中添加对应节(示例 appsettings.Development.json):
json
{
  "System": {
    "UseRedisCache": true
  }
}
  1. 启动时调用注册扩展(通常在应用启动模块或 Startup/Program 中):
csharp
services.AddOptionRegisterService();
  1. 在代码中使用(三种常见方式):
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 已加载;
    • 冲突项是否被更下游的配置源覆盖(例如环境变量/命令行)。
  • 如何在非 Web 场景读取最新配置?
    • 使用 IOptionsMonitor<T> 或在自定义配置变更回调中刷新内部状态。

相关联页面

  • 《缓存》:示例中使用 SystemOptions.UseRedisCache 切换缓存实现。
  • 《IP 限流》:示例中使用 MiddlewareOptions.IpLimit.Enabled 控制中间件启停。

版权所有 © 2021-2026 ApeVolo-Team