如何将 appsetting.json 部分加载到 .NET Core 中的 Dictionary 中?
Posted
技术标签:
【中文标题】如何将 appsetting.json 部分加载到 .NET Core 中的 Dictionary 中?【英文标题】:How to load appsetting.json section into Dictionary in .NET Core? 【发布时间】:2017-08-08 08:21:57 【问题描述】:我熟悉将 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 注入控制器?
【问题讨论】:
嗯,这个问题真的不是关于 ASP.NET Core 而不是 .NET Core 吗?有点误导的标题。 【参考方案1】:采用这种结构格式:
"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);
);
【讨论】:
这对我有用。如果字典更深入部分配置,也可以使用绑定调用。 加上这个,只要你使用services.AddOptions()
from Microsoft.Extensions.Options
,你就不需要使用Bind
。这就够了:services.Configure<CustomSection>(Configuration.GetSection("MobileConfigInfo"));
【参考方案2】:
对于想要将其转换为字典的其他人,
appsettings.json 中的示例部分
"MailSettings":
"Server": "http://mail.mydomain.com"
"Port": "25",
"From": "info@mydomain.com"
下面的代码应该放在 Startup 文件中 > 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"];
一个缺点是所有值都将作为字符串检索,如果您尝试任何其他类型,则该值将为空。
【讨论】:
您不需要.Select(item => new KeyValuePair<string, string>(item.Key, item.Value))
部分。你可以打电话给GetChildren().ToDictionary(x => x.Key, x => x.Value)
。
这应该是公认的答案,这是迄今为止最简单、最优雅的解决方案。
如果您需要非接口的Dictionary<string,string>
,那么您可以致电new Dictionary<string, string>(Configuration.GetSection("mysettings").AsEnumerable())
【参考方案3】:
你可以在startup.cs
类中使用Configuration.Bind(settings);
你的设置类会像
public class AppSettings
public Dictionary<string, string> MobileConfigInfo
get;
set;
希望对你有帮助!
【讨论】:
我试图理解您提供的示例,但它非常令人困惑。settings
是什么?
@Catalin settings
是 AppSettings
类的一个实例。 Bind
方法会将config.json
中的值映射到settings
实例。之后,您可以使用.AddSingleton
或类似的东西将其注入其他类
这不适用于具有Dictionary<string, string>
属性的类。 Bind 方法在运行时失败:System.InvalidOperationException: 'Cannot create instance of type 'System.String' because it is missing a public parameterless constructor.'
【参考方案4】:
相信你可以使用下面的代码:
var config = Configuration.GetSection("MobileConfigInfo").Get<Dictionary<string, string>>();
【讨论】:
为我工作。谢谢!【参考方案5】:到目前为止,最简单的方法是定义您的配置类以从您想要支持的 Dictionary 类型继承。
public class MobileConfigInfo:Dictionary<string, string>
那么您的启动和依赖注入支持将与任何其他配置类型完全相同。
【讨论】:
目前为止最简单的。现在,如果有一种简单的方法可以使用整数作为键...... 这确实是一个 JSON 限制,因为它只允许字符串键。 我认为这应该是公认的答案。一些有助于合并的东西可能是急切的选项验证。就我而言,我想要一个枚举字典,但不想强制在配置中定义每个枚举值。这是一种进行急切验证的方法:github.com/aspnet/Extensions/issues/459#issuecomment-536547483 你是男人中的神【参考方案6】:在 .NET Core 3.1 中,您可以执行以下操作...
appsettings.json:
"myConfig":
"foo": "bar",
"myMappings":
"key1": "value1",
"key2": "value2"
配置模型
MyConfig.cs
public class MyConfig
public string Foo get; set;
public Dictionary<string, string> MyMappings get; set;
Startup.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 字典映射的方式。
【讨论】:
【参考方案7】:对于简单(可能是微服务)应用程序,您可以将其添加为单例 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
【讨论】:
【参考方案8】:我使用下面的方式:
appsettings.json:
"services":
"user-service": "http://user-service:5000/",
"app-service": "http://app-service:5000/"
startup.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;
【讨论】:
不确定为什么这不是最佳答案,因为几乎所有其他答案都错过了 OP 希望通过 IOptions 和依赖注入来消耗它们的事实。无论如何,这对我很有帮助,谢谢。【参考方案9】:唯一对我有用的东西(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));
【讨论】:
【参考方案10】:作为 ASP.Net Core 2.1 中更复杂绑定的示例;根据the documention,我发现使用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;
【讨论】:
这实际上是最好的解决方案。请注意,可以指定一个部分,例如GetSection("Plugins")
但此部分本身不能成为绑定的一部分。尽管即使没有这样的指定 Get<T>
将只绑定现有模型并忽略 json 的所有其他部分。完美的!此外,由于 Net Core 3.5 类属性是可选的。【参考方案11】:
您可以随时进行:
appsettings.json:
"MobileConfigInfo":
"a": "x",
"b": "y",
"c": "z"
代码中的某处:(不要忘记将 IConfiguration 依赖添加到类构造函数中)
var yourDictionary = _configuration.GetSection("MobileConfigInfo")
.Get<IDictionary<string, string>>();
【讨论】:
【参考方案12】:我有一个用于设置字典类型属性的通用解决方案,例如从选项中检索的 html 属性字典。
默认字典值可以在options中设置。如果段中存在相同的键,则覆盖字典中的值,否则插入键值对。
字典为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>
【讨论】:
以上是关于如何将 appsetting.json 部分加载到 .NET Core 中的 Dictionary 中?的主要内容,如果未能解决你的问题,请参考以下文章
<defaultProxy> 的 appsetting.json 版本是啥?
Appsetting.json 读取控制器类中键的值,空白?
如何在appsetting文件中存储API列表和授权密钥[重复]
.net core读取配置文件appsetting.json
解决.net core读取appSetting.json文件中文字符乱码
在 dotnet 核心中,对 config.GetSection().Get <List<object>> 的调用不会将值加载到对象中