如何从 .net 核心中的 appsettings.json 中提取列表
Posted
技术标签:
【中文标题】如何从 .net 核心中的 appsettings.json 中提取列表【英文标题】:How to extract a list from appsettings.json in .net core 【发布时间】:2016-08-26 15:24:36 【问题描述】:我有一个 appsettings.json 文件,如下所示:
"someSetting":
"subSettings": [
"one",
"two",
"three"
]
当我构建我的配置根目录并执行config["someSetting:subSettings"]
之类的操作时,它会返回 null 并且可用的实际设置如下所示:
config["someSettings:subSettings:0"]
有没有更好的方法将someSettings:subSettings
的内容作为列表检索?
【问题讨论】:
也许这行得通.. weblog.west-wind.com/posts/2016/may/23/… 也许吧。我正在使用不是 asp.net 的控制台应用程序,但我会看看我是否可以获取服务集合。 是的,这也适用于控制台应用程序。这与 asp.net 无关 我问只是因为我得到以下信息:Could not load file or assembly 'Microsoft.Extensions.Configuration.Binder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified
你也可以使用 DTO 类来解析配置
【参考方案1】:
假设您的 appsettings.json
如下所示:
"foo":
"bar": [
"1",
"2",
"3"
]
您可以像这样提取列表项:
Configuration.GetSection("foo:bar").Get<List<string>>()
【讨论】:
这对我有用,但我必须先安装“Microsoft.Extensions.Configuration.Binder”NuGet 包,如 here 所述。 要获得键值对象对,您可以使用 json2csharp 创建 C# 类,然后使用 Configuration.GetSection( "foo" ).Get>() 这应该是答案。感谢@Glorfindel 的额外提示! 这对我有用。【参考方案2】:您可以使用配置绑定器来获得配置源的强类型表示。
这是我之前写的一个测试的例子,希望对你有帮助:
[Fact]
public void BindList()
var input = new Dictionary<string, string>
"StringList:0", "val0",
"StringList:1", "val1",
"StringList:2", "val2",
"StringList:x", "valx"
;
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddInMemoryCollection(input);
var config = configurationBuilder.Build();
var list = new List<string>();
config.GetSection("StringList").Bind(list);
Assert.Equal(4, list.Count);
Assert.Equal("val0", list[0]);
Assert.Equal("val1", list[1]);
Assert.Equal("val2", list[2]);
Assert.Equal("valx", list[3]);
重要的部分是对Bind
的调用。
测试和更多示例在GitHub
【讨论】:
自我注意:取决于 Microsoft.Extensions.Configuration.Binder 任何提示如何使用services.Configure<TOptions>
做到这一点?我想从包含数组的配置字段中注入选项【参考方案3】:
在 .NetCore 中我就是这样做的:
正常设置:
在您的 appsettings.json 中为您的自定义定义创建一个配置部分:
"IDP": [
"Server": "asdfsd",
"Authority": "asdfasd",
"Audience": "asdfadf"
,
"Server": "aaaaaa",
"Authority": "aaaaaa",
"Audience": "aaaa"
]
创建一个类来为对象建模:
public class IDP
public String Server get; set;
public String Authority get; set;
public String Audience get; set;
在你的 Startup -> ConfigureServices
services.Configure<List<IDP>>(Configuration.GetSection("IDP"));
注意:如果您需要立即在 ConfigureServices 方法中访问您的列表 你可以使用...
var subSettings = Configuration.GetSection("IDP").Get<List<IDP>>();
然后在你的控制器中是这样的:
Public class AccountController: Controller
private readonly IOptions<List<IDP>> _IDPs;
public AccountController(IOptions<List<Defined>> IDPs)
_IDPs = IDPs;
...
作为一个例子,我在上述控制器的其他地方使用它,如下所示:
_IDPs.Value.ForEach(x =>
// do something with x
);
边缘案例
如果您需要多个配置但它们不能在一个数组中,并且您不知道任何时候您将拥有多少子设置。使用以下方法。
appsettings.json
"IDP":
"0":
"Description": "idp01_test",
"IDPServer": "https://intapi.somedomain.com/testing/idp01/v1.0",
"IDPClient": "someapi",
"Format": "IDP"
,
"1":
"Description": "idpb2c_test",
"IDPServer": "https://intapi.somedomain.com/testing/idpb2c",
"IDPClient": "api1",
"Format": "IDP"
,
"2":
"Description": "MyApp",
"Instance": "https://sts.windows.net/",
"ClientId": "https://somedomain.com/12345678-5191-1111-bcdf-782d958de2b3",
"Domain": "somedomain.com",
"TenantId": "87654321-a10f-499f-9b5f-6de6ef439787",
"Format": "AzureAD"
型号
public class IDP
public String Description get; set;
public String IDPServer get; set;
public String IDPClient get; set;
public String Format get; set;
public String Instance get; set;
public String ClientId get; set;
public String Domain get; set;
public String TenantId get; set;
为 Expando 对象创建扩展
public static class ExpandObjectExtension
public static TObject ToObject<TObject>(this IDictionary<string, object> someSource, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
where TObject : class, new()
Contract.Requires(someSource != null);
TObject targetObject = new TObject();
Type targetObjectType = typeof(TObject);
// Go through all bound target object type properties...
foreach (PropertyInfo property in
targetObjectType.GetProperties(bindingFlags))
// ...and check that both the target type property name and its type matches
// its counterpart in the ExpandoObject
if (someSource.ContainsKey(property.Name)
&& property.PropertyType == someSource[property.Name].GetType())
property.SetValue(targetObject, someSource[property.Name]);
return targetObject;
配置服务
var subSettings = Configuration.GetSection("IDP").Get<List<ExpandoObject>>();
var idx = 0;
foreach (var pair in subSettings)
IDP scheme = ((ExpandoObject)pair).ToObject<IDP>();
if (scheme.Format == "AzureAD")
// this is why I couldn't use an array, AddProtecedWebApi requires a path to a config section
var section = $"IDP:idx.ToString()";
services.AddProtectedWebApi(Configuration, section, scheme.Description);
// ... do more stuff
idx++;
【讨论】:
我创建了一个类来绑定到public class Definitions : List<Defined>
。 ` "定义": [ "名称": "somename", "Title": "sometitle", "Image": "some image url" , "Name": "somename", "Title": "sometitle ", "图片": "一些图片网址" ] `【参考方案4】:
var settingsSection = config.GetSection["someSettings:subSettings"];
var subSettings = new List<string>;
foreach (var section in settingsSection.GetChildren())
subSettings.Add(section.Value);
这应该给你你需要的值,存储在subSettings
很抱歉提出一个半旧的线程。我很难找到答案,因为大量方法已被弃用,例如 Get
和 GetValue
。如果您只需要一个没有配置绑定器的简单解决方案,这应该没问题。 :)
【讨论】:
一个简单的答案,但对我来说有一些变化:var settingsSection = config.GetSection("someSettings:subSettings");
。换句话说,[] 替换为 ()
这个实际上最适合我的用例。【参考方案5】:
在我的情况下配置
services.Configure<List<ApiKey>>(Configuration.GetSection("ApiKeysList"));
没有加载,因为属性是只读的并且没有默认构造函数
//不工作
public class ApiKey : IApiKey
public ApiKey(string key, string owner)
Key = key;
OwnerName = owner;
public string Key get;
public string OwnerName get;
//工作中
public class ApiKey : IApiKey
public ApiKey()//Added default constructor
public ApiKey(string key, string owner)
Key = key;
OwnerName = owner;
public string Key get; set; //Added set property
public string OwnerName get; set; //Added set property
【讨论】:
【参考方案6】:获取整个部分将填充 List 属性;在设置类中。
services.Configure<Settings>(configuration.GetSection("Another:Some:Example"));
但是...请记住,如果在该列表的设置类中设置了默认值...配置设置将是附加的,因此不会覆盖原始值。
因此这些默认值将保留,因此实际上“您无法通过任何其他配置删除它们”
public List<string> NonEditableStuff get; set; = new() "XYZ1", "LTOY3" ;
此外,如果您还打开了 Ini 文件提供程序,可能会很方便地知道要在此处指定列表,只要它们是唯一的,键并不重要,因此保留键和相同的值最终出现在列表中。
[Another:Some:Example:NonEditableStuff]
value=value
whatever2=whatever2
【讨论】:
以上是关于如何从 .net 核心中的 appsettings.json 中提取列表的主要内容,如果未能解决你的问题,请参考以下文章
为asp.net核心中的开发和发布环境自动设置appsettings.json?
从appsettings.json向.net核心控制台应用程序添加多个终结点路由
基于 .Net Core 中的 appSettings 使用 Cors
从 .NET Core 2 中的类中读取 appsettings.json
ConfigurationManager 是不是与 ASP.NET 核心的 appsettings.json 一起使用?