【问题标题】:parse values while configuring options在配置选项时解析值
【发布时间】:2020-10-19 15:01:20
【问题描述】:

我正在使用 .NET Core 并且想要配置我的选项。基于这个示例类

public class MySettings
{
    public Dictionary<int, string> Mapping { get; set; }
}

我在 appsettings.json 文件中添加了一个映射

{
  "MySettings": {
    "Mapping": {
      "9454545": "agf51528gfhdfg",
      "13544": "bfds28745hfghsdfghd"
    }
  }
}

但正如您所见,键是字符串类型,而不是整数。我无法将属性名称更改为数字,因为这样我会收到错误

JSON 属性名称应该是字符串。数字属性名称不是 允许在 JSON 中

所以在启动文件中调用这个的时候

IConfigurationSection mySettingsSection = configuration.GetSection("MySettings");
services.Configure<MySettings>(mySettingsSection);

Mapping 字段将有 0 个项目,因为它无法自动将 JSON 键解析为整数。有没有办法告诉 .NET Core 将这些字符串键解析为整数并填满字典?

【问题讨论】:

  • 为什么不使用Mapping 作为数组而不是对象?
  • 我更新了我的问题。 ID 不代表索引 :)

标签: c# .net-core


【解决方案1】:

嗯,我认为您需要解决方法,因为不能在 json 文件中允许 int。 像这样的:

var mySettingsSection = 
configuration.GetSection("MySettings").Get<Dictionary<string, string>>().Select(x => new KeyValuePair<int, string>(int.Parse(x.Key), x.Value)); 

【讨论】:

  • 这不会返回部分本身。它只返回转换后的字典:(
【解决方案2】:

有没有办法告诉 .NET Core 将这些字符串键解析为整数并填满字典?

很遗憾,没有没有方法可以实现这一目标。

原因

首先,ConfigurationProvider 在内部使用 IDictionary&lt;string, string&gt; 来保存配置设置的键值对 (source code)。

/// <summary>
/// The configuration key value pairs for this provider.
/// </summary>
protected IDictionary<string, string> Data { get; set; }

其次,当JsonConfigurationProvider 尝试解析 JSON 文件(在您的情况下为 appsettings.json)并填充 Data 属性时,解析结果无疑是 IDictionary&lt;string, string&gt; 类型(source code)。

public static IDictionary<string, string> Parse(Stream input)
    => new JsonConfigurationFileParser().ParseStream(input);

private IDictionary<string, string> ParseStream(Stream input)
{
    // Exclude implementation
}

最后,当您调用services.Configure&lt;MySettings&gt;(mySettingsSection) 时,它会调用Bind 方法,通过匹配属性名称(string)与配置键(string)(source code)来填充MySettings 对象。

/// <summary>
/// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
/// </summary>
/// <param name="configuration">The configuration instance to bind.</param>
/// <param name="instance">The object to bind.</param>
/// <param name="configureOptions">Configures the binder options.</param>
public static void Bind(this IConfiguration configuration, object instance, Action<BinderOptions> configureOptions)

因此,在 .NET Core 框架中,从构建配置键值对到将配置绑定到自定义对象,数据流始终围绕 IDictionary&lt;string, string&gt; 类型。此外,没有自定义绑定选项可让您进行任何类型的数据类型转换。

【讨论】:

    【解决方案3】:

    你有两个选择, 第一个是将配置文件更改为 int,string。例如:

    {
      "MySettings": {
        "Mapping": {
          1: "a",
          2: "b"
        }
      }
    }
    

    第二种可能性是在 MySettings 类中创建另一个属性,该属性将具有正确的类型 (Dictionary),在 Mapping 字段中,您可以在 getter 中进行某种转换。

    public class MySettings
    {
        public Dictionary<int, string> Mapping => Config.ToDictionary(a => Int32.Parse(a.Key), a => a.Value);
    
        public Dictionary<int, string> Config { get; set; }
    }
    

    如果您将调用映射多种类型,您可以保存一次转换结果,而不是在每次调用中重新计算。

    【讨论】:

    • 感谢您的回复。第一个选项不起作用,它说json property names should be strings. numeric property names are not allowed in json
    • np :) 我认为您的第二个解决方案应该有效,但我真的不喜欢它。我希望有一个解析配置或类似的东西
    猜你喜欢
    • 2021-06-16
    • 2014-04-25
    • 2010-09-08
    • 2014-09-02
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 2022-10-08
    • 2017-06-27
    相关资源
    最近更新 更多