我在一段时间内第一次创建一个新的控制台应用程序,我正在学习如何使用ihostdservice。如果我想要appsettings中的值。Json可用于我的应用程序,现在正确的方法似乎是这样做:
public static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<MyHostedService>();
services.Configure<MySettings(hostContext.Configuration.GetSection("MySettings"));
services.AddSingleton<MySettings>(container =>
{
return container.GetService<IOptions<MySettings>>().Value;
});
})
.RunConsoleAsync();
}
public class MyHostedService
{
public MyHostedService(MySettings settings)
{
// values from MySettings should be available here
}
}
public class MySettings
{
public string ASetting {get; set;}
public string AnotherSetting {get; set; }
}
// appsettings.json
{
"MySettings": {
"ASetting": "a setting value",
"AnotherSetting": "another value"
}
}
这很有效,很好。然而,如果我想获得我的变量,而不是从应用程序。Json节,但从环境变量?我能看到它们在hostContext中可用。配置和我可以得到单独的值配置。getvalue。但是我需要他们在myhostdservice
我尝试在本地创建它们(即作为Windows中的用户变量),使用双下划线格式,即MySettings_ASetting,但它们似乎不可用或覆盖应用设置。json值。
我想这意味着将它们映射到像MySettings这样的对象,并通过DI以同样的方式传递它,但我不确定如何做到这一点,是否有一个相当于GetSection,或者我是否需要命名我的变量不同,让他们拿起来?
如果您将环境变量声明为ASetting
和AnotherSetting
,那么在ConfigureServices
中,您将需要向持有环境变量的完整IConfiguration
添加绑定,而不仅仅是对具有MySettings
节名/路径的一个绑定,因为该名称/路径也被考虑到查找相应的环境变量-请参阅下面的替代方法。
下面的扩展方法来自Microsoft.Extensions.DependencyInjection
版本7.0.0,它运行在。net 6上,参见文档。
services.AddOptions<MySettings>()
.BindConfiguration("MySettings") // Binds to the appsettings section.
.Bind(hostContext.Configuration); // Binds to e.g. the environment variables.
完整代码:
await Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<MyHostedService>();
services.AddOptions<MySettings>()
.BindConfiguration("MySettings")
.Bind(hostContext.Configuration);
services.AddSingleton<MySettings>(container =>
{
return container.GetService<IOptions<MySettings>>().Value;
});
})
.RunConsoleAsync();
或者,您可以将这些环境变量声明为MySettings:AnotherSetting
和MySettings:AnotherSetting
,在这种情况下,它足以进行以下调用之一:
services.AddOptions<MySettings>().BindConfiguration("MySettings");
或者您已经拥有的代码,没有Bind(hostContext.Configuration)
。
services.Configure<MySettings>(hostContext.Configuration.GetSection("MySettings"));
Edit:
这段代码有问题:
services.AddSingleton<MySettings>(container =>
{
return container.GetService<IOptions<MySettings>>().Value;
});
调用GetService将构建服务提供者,但随后您将尝试向服务提供者添加一个单例。这行不通。你应该在服务中注入IOptions<MySettings>
,而不是。
编辑2:
根据我的经验,双下划线不能很好地工作,如果可以的话,更喜欢使用冒号分隔的键,如MySettings:AnotherValue
。
一个更现代的答案:
MySettings.cs
public class MySettings
{
// Add default configuration path so it can be reused elsewhere
public const string DefaultSectionName = "MySettings";
public string AnotherSetting { get; set; } = string.Empty;
public string ASetting { get; set; } = string.Empty;
}
MyHostedService.cs
public class MyHostedService : IHostedService
{
private readonly MySettings settings;
// IOptions<TOptions> or IOptionsMonitor<TOptions>
// these interfaces add useful extensions features
public MyHostedService(IOptions<MySettings> settings)
{
this.settings = settings.Value;
}
// IHostedService Implementation redacted
}
Progam.cs
// Use top-level statements, linear and fluent service declaration:
var builder = Host.CreateApplicationBuilder(args);
builder.Services
// Declare MyHostedService as a HostedService in the DI engine
.AddHostedService<MyHostedService>()
// Declare IOption<MySettings> (and variants) in the DI engine
.AddOptions<MySettings>()
// Bind the options to the "MySettings" section of the config
.BindConfiguration(MySettings.DefaultSectionName);
await builder.Build().RunAsync();
从命令行或环境中读取设置
默认情况下,主机构建器支持从环境变量加载配置:
属性/launchSettings.json
{
"profiles": {
"run": {
"commandName": "Project",
"environmentVariables": {
"MySettings:AnotherSetting": "test-another"
}
}
}
}
与Host.CreateDefaultBuilder
不同,Host.CreateApplicationBuilder
也支持从CLI加载配置。您可以使用dotnet run --MySettings:AnotherSetting test
来覆盖应用设置的内容。json文件。请注意,在CLI中设置该变量将覆盖环境变量的值。
如果您不想从应用程序设置中获取变量。但是从环境变量中,你可以添加ConfigureAppConfiguration部分或/和ConfigureHostConfiguration到Host
await Host
.CreateDefaultBuilder(args)
.ConfigureHostConfiguration((config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hostsettings.json", optional: true)
.AddEnvironmentVariables(prefix: "PREFIX_");
})
.ConfigureAppConfiguration((hostContext, configBuilder) =>
{
configBuilder
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
// or
.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json",
optional: true, reloadOnChange: true)
//or just any name explicitly
.AddJsonFile(@"C:...mySettings.json")
.Build();
})
.ConfigureServices((hostContext, services) =>
{
services.Configure<MySettings>(hostContext.Configuration.GetSection("MySettings"));
services.AddHostedService<MyHostedService>();
})
.RunConsoleAsync();
和服务
public class MyHostedService : IHostedService
{
private readonly MySettings _settings;
public MyHostedService(IOptions<MySettings> settings)
{
_settings = settings.Value;
}
public Task StartAsync(CancellationToken cancellationToken) {};
public Task StopAsync(CancellationToken cancellationToken) {};
}