[英]How to load appsetting.json section into Dictionary in .NET Core?
我熟悉将 appsettings.json 部分加载到 .NET Core startup.cs 中的强类型对象中。 例如:
public class CustomSection
{
public int A {get;set;}
public int B {get;set;}
}
//In Startup.cs
services.Configure<CustomSection>(Configuration.GetSection("CustomSection"));
//Inject an IOptions instance
public HomeController(IOptions<CustomSection> options)
{
var settings = options.Value;
}
我有一个 appsettings.json 部分,它的键/值对的数量和名称会随着时间的推移而变化。 因此,在类中对属性名称进行硬编码是不切实际的,因为新的键/值对需要在类中进行代码更改。 一些键/值对的小样本:
"MobileConfigInfo": {
"appointment-confirmed": "We've booked your appointment. See you soon!",
"appointments-book": "New Appointment",
"appointments-null": "We could not locate any upcoming appointments for you.",
"availability-null": "Sorry, there are no available times on this date. Please try another."
}
有没有办法将此数据加载到 MobileConfigInfo 字典对象中,然后使用 IOptions 模式将 MobileConfigInfo 注入控制器?
使用这种结构格式:
"MobileConfigInfo": {
"Values": {
"appointment-confirmed": "We've booked your appointment. See you soon!",
"appointments-book": "New Appointment",
"appointments-null": "We could not locate any upcoming appointments for you.",
"availability-null": "Sorry, there are no available times on this date. Please try another."
}
}
让你的设置类看起来像这样:
public class CustomSection
{
public Dictionary<string, string> Values {get;set;}
}
然后这样做
services.Configure<CustomSection>((settings) =>
{
Configuration.GetSection("MobileConfigInfo").Bind(settings);
});
对于其他想要将其转换为Dictionary 的人,
appsettings.json 中的示例部分
"MailSettings": {
"Server": "http://mail.mydomain.com"
"Port": "25",
"From": "info@mydomain.com"
}
以下代码应放在启动文件 > ConfigureServices 方法中:
public static Dictionary<string, object> MailSettings { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
//ConfigureServices code......
MailSettings = Configuration.GetSection("MailSettings").GetChildren()
.ToDictionary(x => x.Key, x => x.Value);
}
现在您可以从任何地方访问字典,例如:
string mailServer = Startup.MailSettings["Server"];
一个缺点是所有值都将作为字符串检索,如果您尝试任何其他类型,则该值将为空。
您可以使用Configuration.Bind(settings);
在startup.cs
类中
你的设置类会像
public class AppSettings
{
public Dictionary<string, string> MobileConfigInfo
{
get;
set;
}
}
希望能帮助到你!
我相信您可以使用以下代码:
var config = Configuration.GetSection("MobileConfigInfo").Get<Dictionary<string, string>>();
到目前为止,最简单的方法是定义您的配置类以从您想要支持的 Dictionary 类型继承。
public class MobileConfigInfo:Dictionary<string, string>{
}
那么您的启动和依赖注入支持将与任何其他配置类型完全相同。
对于简单的(也许是微服务)应用程序,您可以将其添加为单例Dictionary<string, string>
,然后将其注入到您需要的任何位置:
var mobileConfig = Configuration.GetSection("MobileConfigInfo")
.GetChildren().ToDictionary(x => x.Key, x => x.Value);
services.AddSingleton(mobileConfig);
以及用法:
public class MyDependantClass
{
private readonly Dictionary<string, string> _mobileConfig;
public MyDependantClass(Dictionary<string, string> mobileConfig)
{
_mobileConfig = mobileConfig;
}
// Use your mobile config here
}
在 .NET Core 3.1 中,您可以执行以下操作...
appsettings.json:
{
"myConfig": {
"foo": "bar",
"myMappings": {
"key1": "value1",
"key2": "value2"
}
}
}
一个配置模型
配置文件
public class MyConfig
{
public string Foo { get; set; }
public Dictionary<string, string> MyMappings { get; set; }
}
启动.cs:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyConfig>(configuration.GetSection("myConfig"));
使用选项的类:
public class OptionsUsingClass
{
public OptionsUsingClass(IOptions<MyConfig> myConfigOptions)
{
// Be wary of nulls in real code.
var myConfig = myConfigOptions.Value;
// Examples with the above data.
myConfig.Foo.Should().Be("bar");
myConfig.MyMappings["key1"].Should().Be("value1");
myConfig.MyMappings["key2"].Should().Be("value2");
}
这就是我使用 appsettings.json 字典映射的方式。
唯一对我有用(ASP.NET Core 3.0)的是将以下内容添加到Startup.cs
的ConfigureServices
方法中:
services.Configure<Dictionary<string, string>>(dict => Configuration
.GetSection("MySectionName")
.GetChildren()
.ToList()
.ForEach(c => dict[c.Key] = c.Value));
我用下面的方法:
appsettings.json:
"services": {
"user-service": "http://user-service:5000/",
"app-service": "http://app-service:5000/"
}
启动.cs:
services.Configure<Dictionary<string, string>>(Configuration.GetSection("services"));
用法:
private readonly Dictionary<string, string> _services;
public YourConstructor(IOptions<Dictionary<string, string>> servicesAccessor)
{
_services = servicesAccessor.Value;
}
作为 ASP.Net Core 2.1 中更复杂绑定的示例; 根据文档,我发现使用ConfigurationBuilder
.Get<T>()
方法更容易使用。
ASP.NET Core 1.1 及更高版本可以使用 Get,它适用于整个部分。 Get 可以比使用 Bind 更方便。
我在Startup
方法中绑定了配置。
private Config Config { get; }
public Startup(IConfiguration Configuration)
{
Config = Configuration.Get<Config>();
}
这将绑定appsettings
文件:
{
"ConnectionStrings": {
"Accounts": "Server=localhost;Database=Accounts;Trusted_Connection=True;",
"test": "Server=localhost;Database=test;Trusted_Connection=True;",
"Client": "Server=localhost;Database={DYNAMICALLY_BOUND_CONTEXT};Trusted_Connection=True;",
"Support": "Server=localhost;Database=Support;Trusted_Connection=True;"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"Plugins": {
"SMS": {
"RouteMobile": {
"Scheme": "https",
"Host": "remote.host",
"Port": 84567,
"Path": "/bulksms",
"Username": "username",
"Password": "password",
"Source": "CompanyName",
"DeliveryReporting": true,
"MessageType": "Unicode"
}
},
"SMTP": {
"GenericSmtp": {
"Scheme": "https",
"Host": "mail.host",
"Port": 25,
"EnableSsl": true,
"Username": "smtpuser@mail.host",
"Password": "password",
"DefaultSender": "noreply@companyname.co.uk"
}
}
}
}
进入这个配置结构:
[DataContract]
public class Config
{
[DataMember]
public Dictionary<string, string> ConnectionStrings { get; set; }
[DataMember]
public PluginCollection Plugins { get; set; }
}
[DataContract]
public class PluginCollection
{
[DataMember]
public Dictionary<string, SmsConfiguration> Sms { get; set; }
[DataMember]
public Dictionary<string, EmailConfiguration> Smtp { get; set; }
}
[DataContract]
public class SmsConfiguration
{
[DataMember]
public string Scheme { get; set; }
[DataMember]
public string Host { get; set; }
[DataMember]
public int Port { get; set; }
[DataMember]
public string Path { get; set; }
[DataMember]
public string Username { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string Source { get; set; }
[DataMember]
public bool DeliveryReporting { get; set; }
[DataMember]
public string Encoding { get; set; }
}
[DataContract]
public class EmailConfiguration
{
[DataMember]
public string Scheme { get; set; }
[DataMember]
public string Host { get; set; }
[DataMember]
public int Port { get; set; }
[DataMember]
public string Path { get; set; }
[DataMember]
public string Username { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string DefaultSender { get; set; }
[DataMember]
public bool EnableSsl { get; set; }
}
您可以即时完成:
appsettings.json:
{
"MobileConfigInfo": {
"a": "x",
"b": "y",
"c": "z"
}
}
代码中的某处:(不要忘记向类构造函数添加 IConfiguration 依赖项)
var yourDictionary = _configuration.GetSection("MobileConfigInfo")
.Get<IDictionary<string, string>>();
我有一个用于设置字典类型属性的通用解决方案,例如从选项中检索的 HTML 属性字典。
可以在选项中设置默认字典值。 如果该部分中存在相同的键,则覆盖字典中的值,否则插入键值对。
字典的类型是IDictionary<string, object>
并且读取的值没有被解析,它们被设置为类型字符串。
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Extensions.DependencyInjection
{
public static class JJurOptionsExtensions
{
/// <summary>
/// Binding configuration of the property of type IDictionary {string, object}
/// </summary>
/// <typeparam name="TOptions">
/// The type of class that contains the property to be set
/// </typeparam>
/// <param name="services">
/// IoC container
/// </param>
/// <param name="section">
/// Section containing key-value pairs for the dictionary to be set
/// </param>
/// <returns>
/// IServiceCollection
/// </returns>
/// <param name="property">
/// Delegate of the property to be set
/// </param>
public static IServiceCollection ConfigureDictionary<TOptions>(
this IServiceCollection services,
IConfigurationSection section,
Func<TOptions, IDictionary<string, object>> property)
where TOptions : class
{
var values = section // List of sub-sections
.GetChildren()
.ToList();
services.Configure<TOptions>(options =>
{
var dict = property(options);
values.ForEach(v =>
{
// If there is not key, then insert it.
// If there is, override the value.
dict[v.Key] = v.Value;
});
});
return services;
}
}
}
使用示例:
services.Configure<JJurCoreLibs.HtmlSortMnu.SortMenuOptions>(
options => configuration.GetSection("SortMenuOptions").Bind(options)
)
.ConfigureDictionary<JJurCoreLibs.HtmlSortMnu.SortMenuOptions>(
configuration.GetSection("SortMenuOptions:DropDownBbtnHtmlAttributes"),
o => o.DropDownBbtnHtmlAttributes);
SortMenuOptions
类包含一个名为DropDownBtnHtmlAttribute
的属性,其类型为Dictionary<string, object>
。
using System.Collections.Generic;
namespace JJurCoreLibs.HtmlSortMnu
{
/// <summary>
/// Options of the Bootstrap dropdown creating service for sorting items
/// </summary>
public class SortMenuOptions
{
...
public DropDownBbtnHtmlAttributes DropDownBbtnHtmlAttributes { get; } = new DropDownBbtnHtmlAttributes {
{ "role", "button" },
{ "data-toggle", "dropdown" },
{ "aria-expanded", false },
{ "aria-haspopup", true }
};
}
public class DropDownBbtnHtmlAttributes : Dictionary<string, object> { }
}
不更改应用程序设置对我来说更好的方法:
"CustomSection": {
"appointment-confirmed": "We've booked your appointment. See you soon!",
"appointments-book": "New Appointment",
"appointments-null": "We could not locate any upcoming appointments for you.",
"availability-null": "Sorry, there are no available times on this date. Please try another."
}
public class CustomSection : Dictionary<string, string> {}
//In Startup.cs
services.AddOptions<CustomSection>().Bind(Configuration.GetSection("CustomSection"));
//Inject an IOptions instance
public HomeController(IOptions<CustomSection> options)
{
var settings = options.Value;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.