[英]How to load appsetting.json section into Dictionary in .NET Core?
I am familiar w/ loading an appsettings.json section into a strongly typed object in .NET Core startup.cs.我熟悉将 appsettings.json 部分加载到 .NET Core startup.cs 中的强类型对象中。 For example:
例如:
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;
}
I have an appsettings.json section who's key/value pairs will vary in number and name over time.我有一个 appsettings.json 部分,它的键/值对的数量和名称会随着时间的推移而变化。 Therefore, it's not practical to hard code property names in a class since new key/value pairs would require a code change in the class.
因此,在类中对属性名称进行硬编码是不切实际的,因为新的键/值对需要在类中进行代码更改。 A small sample of some key/value pairs:
一些键/值对的小样本:
"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."
}
Is there a way to load this data into a MobileConfigInfo Dictionary object and then use the IOptions pattern to inject MobileConfigInfo into a controller?有没有办法将此数据加载到 MobileConfigInfo 字典对象中,然后使用 IOptions 模式将 MobileConfigInfo 注入控制器?
Go with this structure format:使用这种结构格式:
"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."
}
}
Make your setting class look like this:让你的设置类看起来像这样:
public class CustomSection
{
public Dictionary<string, string> Values {get;set;}
}
then do this然后这样做
services.Configure<CustomSection>((settings) =>
{
Configuration.GetSection("MobileConfigInfo").Bind(settings);
});
For others who want to convert it to a Dictionary ,对于其他想要将其转换为Dictionary 的人,
sample section inside appsettings.json appsettings.json 中的示例部分
"MailSettings": {
"Server": "http://mail.mydomain.com"
"Port": "25",
"From": "info@mydomain.com"
}
Following code should be put inside the Startup file > ConfigureServices method:以下代码应放在启动文件 > 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);
}
Now you can access the dictionary from anywhere like:现在您可以从任何地方访问字典,例如:
string mailServer = Startup.MailSettings["Server"];
One downside is that all values will be retrieved as strings, if you try any other type the value will be null.一个缺点是所有值都将作为字符串检索,如果您尝试任何其他类型,则该值将为空。
You can use Configuration.Bind(settings);
您可以使用
Configuration.Bind(settings);
in startup.cs
class在
startup.cs
类中
And your settings class will be like你的设置类会像
public class AppSettings
{
public Dictionary<string, string> MobileConfigInfo
{
get;
set;
}
}
Hope it helps!希望能帮助到你!
我相信您可以使用以下代码:
var config = Configuration.GetSection("MobileConfigInfo").Get<Dictionary<string, string>>();
By far the simplest method would be to define your configuration class to inherit from the Dictionary type you want to support.到目前为止,最简单的方法是定义您的配置类以从您想要支持的 Dictionary 类型继承。
public class MobileConfigInfo:Dictionary<string, string>{
}
Then your startup and dependency injection support would be exactly the same as for any other configuration type.那么您的启动和依赖注入支持将与任何其他配置类型完全相同。
For simple (perhaps microservice) applications you can just add it it as a singleton Dictionary<string, string>
and then inject it wherever you need it:对于简单的(也许是微服务)应用程序,您可以将其添加为单例
Dictionary<string, string>
,然后将其注入到您需要的任何位置:
var mobileConfig = Configuration.GetSection("MobileConfigInfo")
.GetChildren().ToDictionary(x => x.Key, x => x.Value);
services.AddSingleton(mobileConfig);
And the usage:以及用法:
public class MyDependantClass
{
private readonly Dictionary<string, string> _mobileConfig;
public MyDependantClass(Dictionary<string, string> mobileConfig)
{
_mobileConfig = mobileConfig;
}
// Use your mobile config here
}
In .NET Core 3.1 you can do something like the following...在 .NET Core 3.1 中,您可以执行以下操作...
appsettings.json: appsettings.json:
{
"myConfig": {
"foo": "bar",
"myMappings": {
"key1": "value1",
"key2": "value2"
}
}
}
A configuration model一个配置模型
MyConfig.cs配置文件
public class MyConfig
{
public string Foo { get; set; }
public Dictionary<string, string> MyMappings { get; set; }
}
Startup.cs:启动.cs:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyConfig>(configuration.GetSection("myConfig"));
Class using the options:使用选项的类:
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");
}
This was how I used appsettings.json dictionary mappings.这就是我使用 appsettings.json 字典映射的方式。
The only thing that worked for me (ASP.NET Core 3.0) was to add the following to the ConfigureServices
method of Startup.cs
:唯一对我有用(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));
I use the way below:我用下面的方法:
appsettings.json: appsettings.json:
"services": {
"user-service": "http://user-service:5000/",
"app-service": "http://app-service:5000/"
}
startup.cs:启动.cs:
services.Configure<Dictionary<string, string>>(Configuration.GetSection("services"));
Usage:用法:
private readonly Dictionary<string, string> _services;
public YourConstructor(IOptions<Dictionary<string, string>> servicesAccessor)
{
_services = servicesAccessor.Value;
}
As an example of more complex binding in ASP.Net Core 2.1;作为 ASP.Net Core 2.1 中更复杂绑定的示例; I found using the
ConfigurationBuilder
.Get<T>()
method far easier to work with, as per the documention . 根据文档,我发现使用
ConfigurationBuilder
.Get<T>()
方法更容易使用。
ASP.NET Core 1.1 and higher can use Get, which works with entire sections.
ASP.NET Core 1.1 及更高版本可以使用 Get,它适用于整个部分。 Get can be more convenient than using Bind.
Get 可以比使用 Bind 更方便。
I bound the configuration in my Startup
method.我在
Startup
方法中绑定了配置。
private Config Config { get; }
public Startup(IConfiguration Configuration)
{
Config = Configuration.Get<Config>();
}
This binds the appsettings
file:这将绑定
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"
}
}
}
}
Into this configuration structure:进入这个配置结构:
[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; }
}
You can do it on the fly:您可以即时完成:
appsettings.json:
{
"MobileConfigInfo": {
"a": "x",
"b": "y",
"c": "z"
}
}
Somewhere in code: (don't forget to add IConfiguration dependency to the class constructor)代码中的某处:(不要忘记向类构造函数添加 IConfiguration 依赖项)
var yourDictionary = _configuration.GetSection("MobileConfigInfo")
.Get<IDictionary<string, string>>();
I have a generic solution for setting dictionary type properties, such as the dictionary of HTML attributes that are retrieved from options.我有一个用于设置字典类型属性的通用解决方案,例如从选项中检索的 HTML 属性字典。
Default dictionary values can be set in options.可以在选项中设置默认字典值。 If the same key exists in the section, then the value in the dictionary is overwritten, otherwise a key-value pair is inserted.
如果该部分中存在相同的键,则覆盖字典中的值,否则插入键值对。
The dictionary is of type IDictionary<string, object>
and the read values are not parsed, they are set as type string.字典的类型是
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;
}
}
}
An example of use:使用示例:
services.Configure<JJurCoreLibs.HtmlSortMnu.SortMenuOptions>(
options => configuration.GetSection("SortMenuOptions").Bind(options)
)
.ConfigureDictionary<JJurCoreLibs.HtmlSortMnu.SortMenuOptions>(
configuration.GetSection("SortMenuOptions:DropDownBbtnHtmlAttributes"),
o => o.DropDownBbtnHtmlAttributes);
The SortMenuOptions
class contains a property named DropDownBtnHtmlAttribute
of type Dictionary<string, object>
. 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> { }
}
The better way for me without changing appsetting:不更改应用程序设置对我来说更好的方法:
"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.