在 AppConfig.json 中存储对象的最佳方式
Optimal way to store objects in AppConfig.json
我的AppConfig.json:
{
"MyTimeZone: "CET",
"RegularString" : "SomeValue",
"AnArray" : ["1","2"]
}
我的 POCO class:
public class Settings
{
public TimeZoneInfo MyTimeZone { get; set; }
public string RegularString { get; set; }
public IList<string> AnArray { get; set; }
}
Registry.cs:
var configuration = GetConfiguration("AppSettings.json");
services.Configure<Settings>(configuration.GetSection("Settings"));
这当然不会将“CET”绑定到有效的 TimeZoneInfo 对象中。现在的问题是我的应用程序(一个网络应用程序)中从字符串转换为 TimeZoneInfo 的最佳位置是什么?有没有一种方法可以根据特定规则自动将字符串配置值转换为对象,而无需创建自定义转换器?
引用Use DI services to configure options
services.AddOptions<Settings>()
.Configure<IConfiguration>((setting, configuration) => {
var section = config.GetSection("Settings");
//This will populate the other properties that can bind by default
section.Bind(setting);
//this will extract the remaining value and set it mnually
string value = section.GetValue<string>("MyTimeZone");
TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(value);
setting.MyTimeZone = info;
});
复杂的设置值可以通过 DI 直接从配置中提取,用于创建时区并将其应用于设置。
这只是我个人的意见,但我更喜欢 MyTimeZone 是一个 json 对象而不是一个字符串。考虑以下因素:
"Settings": {
"MyTimeZone": {
"ConfigureTimeZoneById": "CET"
},
"RegularString": "SomeValue",
"AnArray": [ "1", "2" ]
}
MyTimeZone.ConfigureTimeZoneById 不是实际数据对象的一部分。它只是将对象绑定到配置的代理。这就是 TimeZone class 的样子:
public class TimeZone
{
private string configureTimeZoneById { get; set; }
public string ConfigureTimeZoneById
{
get { return configureTimeZoneById; }
set
{
configureTimeZoneById = value;
InitializeTimeZone(value);
}
}
public string TimeZoneId { get; set; }
public string OtherProperties { get; set; }
private void InitializeTimeZone(string id)
{
var getTimeZone = TimeZonesDataset().FirstOrDefault(tzon => tzon.TimeZoneId.Equals(id));
if (getTimeZone != null)
{
this.TimeZoneId = getTimeZone.TimeZoneId;
this.OtherProperties = getTimeZone.OtherProperties;
}
}
//dummy dataset
private List<TimeZone> TimeZonesDataset() => new List<TimeZone> {
new TimeZone{TimeZoneId = "CET", OtherProperties = "Dummy properties to prove point"},
new TimeZone{TimeZoneId = "GMT", OtherProperties = default},
};
我的AppConfig.json:
{
"MyTimeZone: "CET",
"RegularString" : "SomeValue",
"AnArray" : ["1","2"]
}
我的 POCO class:
public class Settings
{
public TimeZoneInfo MyTimeZone { get; set; }
public string RegularString { get; set; }
public IList<string> AnArray { get; set; }
}
Registry.cs:
var configuration = GetConfiguration("AppSettings.json");
services.Configure<Settings>(configuration.GetSection("Settings"));
这当然不会将“CET”绑定到有效的 TimeZoneInfo 对象中。现在的问题是我的应用程序(一个网络应用程序)中从字符串转换为 TimeZoneInfo 的最佳位置是什么?有没有一种方法可以根据特定规则自动将字符串配置值转换为对象,而无需创建自定义转换器?
引用Use DI services to configure options
services.AddOptions<Settings>()
.Configure<IConfiguration>((setting, configuration) => {
var section = config.GetSection("Settings");
//This will populate the other properties that can bind by default
section.Bind(setting);
//this will extract the remaining value and set it mnually
string value = section.GetValue<string>("MyTimeZone");
TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(value);
setting.MyTimeZone = info;
});
复杂的设置值可以通过 DI 直接从配置中提取,用于创建时区并将其应用于设置。
这只是我个人的意见,但我更喜欢 MyTimeZone 是一个 json 对象而不是一个字符串。考虑以下因素:
"Settings": {
"MyTimeZone": {
"ConfigureTimeZoneById": "CET"
},
"RegularString": "SomeValue",
"AnArray": [ "1", "2" ]
}
MyTimeZone.ConfigureTimeZoneById 不是实际数据对象的一部分。它只是将对象绑定到配置的代理。这就是 TimeZone class 的样子:
public class TimeZone
{
private string configureTimeZoneById { get; set; }
public string ConfigureTimeZoneById
{
get { return configureTimeZoneById; }
set
{
configureTimeZoneById = value;
InitializeTimeZone(value);
}
}
public string TimeZoneId { get; set; }
public string OtherProperties { get; set; }
private void InitializeTimeZone(string id)
{
var getTimeZone = TimeZonesDataset().FirstOrDefault(tzon => tzon.TimeZoneId.Equals(id));
if (getTimeZone != null)
{
this.TimeZoneId = getTimeZone.TimeZoneId;
this.OtherProperties = getTimeZone.OtherProperties;
}
}
//dummy dataset
private List<TimeZone> TimeZonesDataset() => new List<TimeZone> {
new TimeZone{TimeZoneId = "CET", OtherProperties = "Dummy properties to prove point"},
new TimeZone{TimeZoneId = "GMT", OtherProperties = default},
};