Skip to content

在 .NET Core 的配置系统中,IOptions<T>IOptionsSnapshot<T>IOptionsMonitor<T> 是用于将配置文件(如 appsettings.json)中的配置项注入到服务中的三种主要方式。它们的区别在于生命周期和配置更新行为


📌 三者的定义与作用

1. IOptions<T>

  • 生命周期Singleton(单例)
  • 特点
    • 配置在应用启动时读取一次,之后不会自动更新
    • 所有地方注入的 IOptions<T> 都是同一个实例。
    • 即使你修改了 appsettings.json 文件并保存,已启动的应用也不会感知到变化。
  • 适用场景
    • 配置项在应用运行期间几乎不变,如数据库连接字符串(虽然可以热更新,但 IOptions<T> 不支持)。
    • 性能要求高,且不需要动态更新配置。

注册方式:自动支持,无需额外配置。

csharp
// 使用
public class MyService
{
    private readonly MyConfig _config;

    public MyService(IOptions<MyConfig> options)
    {
        _config = options.Value;
    }
}

2. IOptionsSnapshot<T>

  • 生命周期Scoped(作用域)
  • 特点
    • 每个请求(作用域)开始时读取一次配置。
    • 如果你在 appsettings.json 中修改了配置,并发起一个新请求,新请求会读取最新的配置。
    • 在同一个请求内,多次获取 IOptionsSnapshot<T> 得到的是同一个值。
  • 适用场景
    • 配置可能在运行时更改,且你希望每个请求能获取最新的配置
    • Web 应用中最常用的配置注入方式。

注意:它依赖于文件的 reloadOnChange: true 设置。

json
// appsettings.json
{
  "MyConfig": {
    "ApiKey": "12345",
    "Timeout": 30
  }
}
csharp
// Program.cs
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

// 使用
public class MyService
{
    private readonly MyConfig _config;

    public MyService(IOptionsSnapshot<MyConfig> options)
    {
        _config = options.Value; // 每个请求获取一次最新值
    }
}

3. IOptionsMonitor<T>

  • 生命周期Singleton(单例)
  • 特点
    • 可以实时监听配置变化,并在配置更新时触发回调。
    • 提供 CurrentValue 属性,始终返回最新值。
    • 支持更改回调OnChange),可以在配置变化时执行逻辑(如重新加载缓存)。
    • 支持命名选项(Named Options),即同一类型不同配置。
  • 适用场景
    • 需要实时响应配置变化,如动态开关、限流阈值、功能启用等。
    • 需要在配置更新时执行某些操作(如日志记录、缓存刷新)。
csharp
public class MyService
{
    private readonly IOptionsMonitor<MyConfig> _options;

    public MyService(IOptionsMonitor<MyConfig> options)
    {
        _options = options;

        // 监听配置变化
        _options.OnChange(config =>
        {
            Console.WriteLine($"配置已更新!新 API Key: {config.ApiKey}");
            // 可以在这里刷新缓存、重新初始化服务等
        });
    }

    public MyConfig GetCurrentConfig()
    {
        return _options.CurrentValue; // 始终是最新值
    }
}

🆚 三者对比总结

特性IOptions<T>IOptionsSnapshot<T>IOptionsMonitor<T>
生命周期SingletonScopedSingleton
配置更新❌ 不支持✅ 每个请求更新✅ 实时更新
是否触发回调✅ 支持 OnChange
同一请求内一致性
跨请求共享❌(每请求不同)
适用场景静态配置Web 请求级配置更新实时监听 + 回调

✅ 如何选择?

场景推荐使用
配置启动后不变(如 AppSettings:SiteNameIOptions<T>
Web 应用,希望每个请求能读取最新配置IOptionsSnapshot<T> ✅(最常用)
需要监听配置变化并执行逻辑(如动态开关)IOptionsMonitor<T>
多套同类型配置(如多个数据库配置)IOptionsMonitor<T>(支持命名选项)

💡 示例:配置文件热更新

json
// appsettings.json
{
  "MyConfig": {
    "ApiKey": "initial-key",
    "FeatureEnabled": true
  }
}
csharp
// MyConfig.cs
public class MyConfig
{
    public string ApiKey { get; set; }
    public bool FeatureEnabled { get; set; }
}
csharp
// 注册(自动支持)
builder.Services.Configure<MyConfig>(builder.Configuration.GetSection("MyConfig"));
csharp
// 使用 IOptionsSnapshot(推荐 Web 项目)
public class ConfigController : ControllerBase
{
    private readonly IOptionsSnapshot<MyConfig> _config;

    public ConfigController(IOptionsSnapshot<MyConfig> config)
    {
        _config = config;
    }

    [HttpGet]
    public IActionResult Get()
    {
        return Ok(_config.Value);
        // 修改 appsettings.json 并保存后,刷新页面即可看到新值
    }
}

✅ 最佳实践

  • 🌐 ASP.NET Core Web 项目:优先使用 IOptionsSnapshot<T>
  • ⚙️ 需要实时响应配置变化:使用 IOptionsMonitor<T> + OnChange
  • 🧱 静态配置、高性能场景:使用 IOptions<T>
  • 🔁 确保 reloadOnChange: true 启用:
csharp
// Program.cs
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

总结

接口用法类比
IOptions<T>一次性读取,永不更新“只读一次”
IOptionsSnapshot<T>每个请求读取一次“每请求刷新”
IOptionsMonitor<T>实时监听,随时获取最新值“订阅模式”

在大多数 Web 项目中,IOptionsSnapshot<T> 是最常用的选择,因为它平衡了性能和灵活性。