.NET 1.1.4迁移至2.0:UseKestrel能否访问hostContext?
针对你提到的两个核心问题,我来逐一拆解说明:
1. UseKestrel能否访问hostContext参数?
当然可以!你可能之前只留意到了UseKestrel的单参数重载(仅接收KestrelServerOptions),但它确实存在一个双参数重载,允许你同时获取HostBuilderContext(也就是你说的hostContext)和KestrelServerOptions。
示例代码如下:
Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostContext, config) => { // 你的自定义配置逻辑,比如添加额外配置文件 config.AddJsonFile("customsettings.json", optional: true); }) .UseKestrel((hostContext, kestrelOptions) => { // 这里直接访问hostContext,读取配置里的Kestrel端口 var kestrelPort = hostContext.Configuration.GetValue<int>("Kestrel:Endpoints:Http:Port"); kestrelOptions.ListenAnyIP(kestrelPort); // 还能通过hostContext获取环境信息,比如判断是否为开发环境 if (hostContext.HostingEnvironment.IsDevelopment()) { kestrelOptions.AllowSynchronousIO = true; } }) .ConfigureServices((hostContext, services) => { // ... 其他服务配置逻辑 }) .Build();
这个重载在.NET Core 2.0及以上版本就已存在,完全能满足你访问hostContext的需求。
2. ConfigureAppConfiguration中配置的复用:无需重新实例化ConfigurationBuilder
你完全没必要重新构建ConfigurationBuilder来复用配置!有两种简单且规范的方式:
方式一:在后续Configure*方法中直接通过hostContext访问
当你在ConfigureAppConfiguration中完成配置后,hostContext.Configuration已经是构建完成的IConfigurationRoot实例,包含了你添加的所有配置源(包括默认的appsettings.json、环境变量等)。在UseKestrel、ConfigureServices等后续方法里,直接通过hostContext.Configuration读取配置即可:
Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostContext, config) => { config.AddJsonFile("appsettings.json", optional: false); config.AddEnvironmentVariables(); }) .UseKestrel((hostContext, options) => { // 直接复用已配置好的hostContext.Configuration var maxRequestSize = hostContext.Configuration.GetValue<long>("Kestrel:Limits:MaxRequestBodySize"); options.Limits.MaxRequestBodySize = maxRequestSize; }) .ConfigureServices((hostContext, services) => { // 同样在ConfigureServices里也能直接使用 var connectionString = hostContext.Configuration.GetConnectionString("DefaultConnection"); services.AddDbContext<MyDbContext>(opt => opt.UseSqlServer(connectionString)); }) .Build();
方式二:在ConfigureAppConfiguration内部存储配置根(可选)
如果需要在ConfigureAppConfiguration方法内部复用配置,你可以手动构建配置根并存储到函数作用域的变量中(注意变量要定义在HostBuilder外部):
IConfigurationRoot _configRoot = null; Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostContext, config) => { config.AddJsonFile("appsettings.json", optional: false); // 构建配置根并存储 _configRoot = config.Build(); // 内部直接复用配置 var apiKey = _configRoot.GetValue<string>("ApiSettings:ApiKey"); Console.WriteLine($"Loaded API Key: {apiKey}"); }) .UseKestrel((hostContext, options) => { // 这里也可以使用存储的_configRoot变量 var port = _configRoot.GetValue<int>("Kestrel:Port"); options.ListenAnyIP(port); }) .Build();
不过这种方式不如第一种规范,因为hostContext.Configuration是HostBuilder统一管理的最终配置,会包含默认配置源(比如命令行参数),而手动构建的_configRoot可能会漏掉这些默认项,所以更推荐第一种方式。
内容的提问来源于stack exchange,提问作者user6728767

