You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 2.0非控制器类中使用IOptionsSnapshot的方法

嗨,这个问题我熟!在.NET Core 2.0里,非控制器类要获取IOptionsSnapshot<AppConfiguration>其实和控制器逻辑一致——核心是依赖注入,别想着直接new普通类,让DI容器帮你管理依赖就好。下面分两种常见场景给你详细说明:

1. 给普通类添加构造注入并注册到DI容器

首先,让你的TestClass通过构造函数接收IOptionsSnapshot<AppConfiguration>,就像控制器那样:

public class TestClass
{
    private readonly AppConfiguration _appConfig;

    // 构造注入IOptionsSnapshot
    public TestClass(IOptionsSnapshot<AppConfiguration> options)
    {
        _appConfig = options.Value;
    }

    public void DoBusinessLogic()
    {
        // 直接使用配置项,比如:
        Console.WriteLine($"当前API地址:{_appConfig.ApiUrl}");
    }
}

然后,在Startup.cs的ConfigureServices方法里,把TestClass注册到DI容器中(根据你的业务需求选择生命周期:Transient/Scoped/Singleton):

public void ConfigureServices(IServiceCollection services)
{
    // 你已有的配置绑定代码
    services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));

    // 注册普通类到DI容器,用Scoped和IOptionsSnapshot的生命周期匹配更合理
    services.AddScoped<TestClass>();

    // 其他服务注册(比如MVC等)
    services.AddMvc();
}

之后,当你需要使用TestClass时,不要直接new TestClass(),而是通过DI容器获取:比如在另一个服务的构造函数里注入TestClass,或者在控制器里注入它——和你用控制器获取配置的逻辑完全一样。

2. 在Startup流程中直接获取(比如Configure方法里)

如果是在Startup的流程中(比如Configure方法里,还没有控制器被调用)需要使用IOptionsSnapshot或者TestClass,你可以通过IServiceProvider来获取,但要注意IOptionsSnapshot是Scoped生命周期的,所以必须先创建一个临时作用域:

方式一:直接获取IOptionsSnapshot

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
    // 创建临时作用域
    using (var scope = serviceProvider.CreateScope())
    {
        var options = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<AppConfiguration>>();
        var appConfig = options.Value;
        
        // 使用配置做初始化操作
        Console.WriteLine($"初始化时读取到的API地址:{appConfig.ApiUrl}");
    }

    // 其他中间件配置
    app.UseMvc();
}

方式二:获取注册好的TestClass

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
    using (var scope = serviceProvider.CreateScope())
    {
        var testClass = scope.ServiceProvider.GetRequiredService<TestClass>();
        testClass.DoBusinessLogic();
    }

    app.UseMvc();
}

⚠️ 注意:尽量避免在ConfigureServices方法里直接获取IOptionsSnapshot,因为此时DI容器还没完全初始化,且没有默认作用域。如果一定要在ConfigureServices里用,需要手动构建临时服务提供者并创建作用域:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<AppConfiguration>(Configuration.GetSection("AppConfiguration"));
    services.AddScoped<TestClass>();

    // 仅在必要时使用这种方式
    using (var tempProvider = services.BuildServiceProvider())
    using (var scope = tempProvider.CreateScope())
    {
        var testClass = scope.ServiceProvider.GetRequiredService<TestClass>();
        testClass.DoBusinessLogic();
    }
}

最后提醒一句:优先用构造注入的方式,这是.NET Core依赖注入的最佳实践,代码更易测试、更符合开闭原则;服务定位器模式(直接从IServiceProvider获取)只作为特殊场景的补充。

内容的提问来源于stack exchange,提问作者Lukas Hieronimus Adler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:46:24