从注入配置 class 访问 AppSettings.json 中的顶级字段
Accessing top-level fields in AppSettings.json from injected configuration class
假设我们有这样的 AppSettings.json
{
"Region": Europe,
"WeirdService": {
"JustField": "value"
}
}
在单独的单例 class 中注册 WeirdService
设置(或使用选项模式)没问题,只是:
service.AddSingleton(configuration.GetSection("WeirdService").Get<WeirdService>();
此时一切正常。但是我不知道如何干净地处理这个顶级属性,例如我的示例中的 Region
。
我知道我可以直接注入 IConfiguration
并使用 config.GetValue<string>("Region")
或者直接访问配置,但我想知道是否有一些干净、更好的方法而不用在服务中硬编码这些东西。
编辑
忘记说了。我目前合作的团队使用 .NET Core 3.1 作为当前的 LTS 版本。
您也可以将部分绑定到 class,它允许在不使用太多魔术字符串的情况下进行干净的使用。
public class WeirdService{
public string JustField{ get; set;}
public string AnotherField{ get; set;}
}
然后您可以在控制器中定义一个字段
private readonly WeirdService _weirdService = new WeirdService();
public UserController(IConfiguration configuration)
{
configuration.GetSection("WeirdService").Bind(_weirdService);
//_weirdService.JustField
//_weirdService.AnotherField
}
您可以使用
访问区域字段
configuration.GetValue<string>("Region")
或者其他方式是
public Startup(IConfiguration configuration, IWebHostEnvironment
webHostEnvironment)
{
Configuration = configuration;
environment = webHostEnvironment;
}
那你就可以用
Configuration["Region"]
已更新
方法 1 首选方式
读取相关配置值的首选方法是使用 options pattern
.
有关 options pattern
的更多详细信息,请查看下面的 link。
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0
"WeirdService": {
"JustField": "value"
}
创建 WeiredServiceOptions
class.
public class WeiredServiceOptions
{
public const string WeiredService = "WeiredService";
public string JustField { get; set; }
}
一个选项class:
- 必须是非抽象的 public 无参数构造函数。
- 该类型的所有 public 读写属性都已绑定。
- 字段未绑定。在前面的代码中,
WeiredService
未绑定。使用 Position 属性,因此在将 class 绑定到配置提供程序时,不需要在应用程序中对字符串 WeiredService 进行硬编码。
调用 ConfigurationBinder.Bind
将 WeiredServiceOption
s class 绑定到 WeiredService 部分。
var weiredServiceOptions = new PositionOptions();
configuration.GetSection(PositionOptions.Position).Bind(positionOptions);
使用选项模式时的另一种方法是绑定 WeiredService 部分并将其添加到 dependency injection service container
。在下面的代码中,WeiredServiceOptions是用Configure添加到服务容器中并绑定到配置
services.Configure<WeiredServiceOptions>(Configuration.GetSection(
WeiredServiceOptions.Position));
然后阅读 WeiredService 选项。
private readonly WeiredServiceOptions _options;
public YourClassContructor(IOptions<WeiredServiceOptions> options)
{
_options = options
}
Console.WriteLine($"JustField: {_options.JustField}");
方法二
service.AddSingleton(configuration.GetSection("WeirdService:JustField").value);
方法三
service.AddSingleton(configuration["WeirdService:JustField"]);
你有两个选择
没有任何顶级字段
所有顶级字段都将进入一个级别。您的配置如下所示:
{
"App": {
"Region": "east-us-2",
"ShowMaintenancePrompt": false
},
// other options follow
}
这种方法的优点是您可以随着应用程序的增长不断添加 "App"
,并继续使用选项模式。
将顶级字段收集到 class 中,并使用 DI
进行注册
对于这样的配置:
{
"Region": "east-us-2"
}
创建 AppConfig class 如:
internal class AppConfig
{
public string? Region { get; set; }
}
然后用 DI 注册这个 class:
var toplevelConfig = new AppConfig {
Region = configuration.GetValue<string>("Region")
};
services.AddSingleton<AppConfig>(toplevelConfig);
您现在可以在任何地方注入 AppConfig
。
唯一的小缺点是您不能再使用选项模式。
避免直接注入 IConfiguration
。
我认为最简单的方法是为顶级键创建一个 class。在您的情况下,您可以使用单个 属性 区域创建类似 AppConfig 的内容。然后您只需注册它而不使用 Configuration 对象获取配置部分,Configure 方法无论如何都要求配置接口而不是 ConfigurationSection。
应用程序配置:
public class AppConfig
{
public string? Region { get; set; }
}
报名人数:
public static IServiceCollection AddOptions(this IServiceCollection services, IConfiguration configuration)
{
return services.Configure<AppConfig>(configuration);
}
用法:
public class ExampleConsumer
{
public ExampleConsumer(IOptions<AppConfig> appConfig) {}
}
假设我们有这样的 AppSettings.json
{
"Region": Europe,
"WeirdService": {
"JustField": "value"
}
}
在单独的单例 class 中注册 WeirdService
设置(或使用选项模式)没问题,只是:
service.AddSingleton(configuration.GetSection("WeirdService").Get<WeirdService>();
此时一切正常。但是我不知道如何干净地处理这个顶级属性,例如我的示例中的 Region
。
我知道我可以直接注入 IConfiguration
并使用 config.GetValue<string>("Region")
或者直接访问配置,但我想知道是否有一些干净、更好的方法而不用在服务中硬编码这些东西。
编辑
忘记说了。我目前合作的团队使用 .NET Core 3.1 作为当前的 LTS 版本。
您也可以将部分绑定到 class,它允许在不使用太多魔术字符串的情况下进行干净的使用。
public class WeirdService{
public string JustField{ get; set;}
public string AnotherField{ get; set;}
}
然后您可以在控制器中定义一个字段
private readonly WeirdService _weirdService = new WeirdService();
public UserController(IConfiguration configuration)
{
configuration.GetSection("WeirdService").Bind(_weirdService);
//_weirdService.JustField
//_weirdService.AnotherField
}
您可以使用
访问区域字段configuration.GetValue<string>("Region")
或者其他方式是
public Startup(IConfiguration configuration, IWebHostEnvironment
webHostEnvironment)
{
Configuration = configuration;
environment = webHostEnvironment;
}
那你就可以用
Configuration["Region"]
已更新
方法 1 首选方式
读取相关配置值的首选方法是使用 options pattern
.
有关 options pattern
的更多详细信息,请查看下面的 link。
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0
"WeirdService": {
"JustField": "value"
}
创建 WeiredServiceOptions
class.
public class WeiredServiceOptions
{
public const string WeiredService = "WeiredService";
public string JustField { get; set; }
}
一个选项class:
- 必须是非抽象的 public 无参数构造函数。
- 该类型的所有 public 读写属性都已绑定。
- 字段未绑定。在前面的代码中,
WeiredService
未绑定。使用 Position 属性,因此在将 class 绑定到配置提供程序时,不需要在应用程序中对字符串 WeiredService 进行硬编码。
调用 ConfigurationBinder.Bind
将 WeiredServiceOption
s class 绑定到 WeiredService 部分。
var weiredServiceOptions = new PositionOptions();
configuration.GetSection(PositionOptions.Position).Bind(positionOptions);
使用选项模式时的另一种方法是绑定 WeiredService 部分并将其添加到 dependency injection service container
。在下面的代码中,WeiredServiceOptions是用Configure添加到服务容器中并绑定到配置
services.Configure<WeiredServiceOptions>(Configuration.GetSection(
WeiredServiceOptions.Position));
然后阅读 WeiredService 选项。
private readonly WeiredServiceOptions _options;
public YourClassContructor(IOptions<WeiredServiceOptions> options)
{
_options = options
}
Console.WriteLine($"JustField: {_options.JustField}");
方法二
service.AddSingleton(configuration.GetSection("WeirdService:JustField").value);
方法三
service.AddSingleton(configuration["WeirdService:JustField"]);
你有两个选择
没有任何顶级字段
所有顶级字段都将进入一个级别。您的配置如下所示:
{
"App": {
"Region": "east-us-2",
"ShowMaintenancePrompt": false
},
// other options follow
}
这种方法的优点是您可以随着应用程序的增长不断添加 "App"
,并继续使用选项模式。
将顶级字段收集到 class 中,并使用 DI
进行注册对于这样的配置:
{
"Region": "east-us-2"
}
创建 AppConfig class 如:
internal class AppConfig
{
public string? Region { get; set; }
}
然后用 DI 注册这个 class:
var toplevelConfig = new AppConfig {
Region = configuration.GetValue<string>("Region")
};
services.AddSingleton<AppConfig>(toplevelConfig);
您现在可以在任何地方注入 AppConfig
。
唯一的小缺点是您不能再使用选项模式。
避免直接注入 IConfiguration
。
我认为最简单的方法是为顶级键创建一个 class。在您的情况下,您可以使用单个 属性 区域创建类似 AppConfig 的内容。然后您只需注册它而不使用 Configuration 对象获取配置部分,Configure 方法无论如何都要求配置接口而不是 ConfigurationSection。
应用程序配置:
public class AppConfig
{
public string? Region { get; set; }
}
报名人数:
public static IServiceCollection AddOptions(this IServiceCollection services, IConfiguration configuration)
{
return services.Configure<AppConfig>(configuration);
}
用法:
public class ExampleConsumer
{
public ExampleConsumer(IOptions<AppConfig> appConfig) {}
}