首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >键中带有冒号的Microsoft.Extensions.Configuration绑定字典

键中带有冒号的Microsoft.Extensions.Configuration绑定字典
EN

Stack Overflow用户
提问于 2016-12-21 09:37:36
回答 2查看 5.4K关注 0票数 5

我在使用Microsoft.Extensions.Configuration绑定包含包含冒号:的键的字典时遇到了问题。

我已经做了一个例子,它有一个字典"GoodErrorMappings“,它在键中不包含任何冒号。这些映射是正确的。

我已经创建了另一个字典"BadErrorMappings“,它的键中有一个冒号。在字典键中看到第一个冒号后,该字典似乎没有被正确地映射。

我已经快速地查看了源代码,并且看不到一个明显的方法来覆盖冒号作为分隔符。

任何帮助都将不胜感激。

Doco: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration

汇编版本: "Microsoft.NETCore.App“"1.1.0”

C#代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace OptionsTest
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json");

            var config = builder.Build();

            var services = new ServiceCollection().AddOptions();

            services.Configure<ApiConfig>(x => config.GetSection("ApiConfig").Bind(x));

            var apiConfig = services.BuildServiceProvider().GetService<IOptions<ApiConfig>>().Value;

            Debug.WriteLine(string.Format("\r\nGoodErrorMappings: {0}", JsonConvert.SerializeObject(apiConfig.GoodErrorMappings, Formatting.Indented)));
            Debug.WriteLine(string.Format("\r\nBadErrorMappings: {0}", JsonConvert.SerializeObject(apiConfig.BadErrorMappings, Formatting.Indented)));

            Console.ReadLine();
        }
    }

    public class ApiConfig
    {
        public Dictionary<string, ErrorMapping> GoodErrorMappings { get; set; } = new Dictionary<string, ErrorMapping>();
        public Dictionary<string, ErrorMapping> BadErrorMappings { get; set; } = new Dictionary<string, ErrorMapping>();
    }

    public class ErrorMapping
    {
        public int HttpStatusCode { get; set; }
        public int ErrorCode { get; set; }
        public string Description { get; set; }
    }
}

AppSettings.json:

代码语言:javascript
复制
{
  "ApiConfig": {
    "GoodErrorMappings": {
      "/SOMEVALUE/BLAH.123": {
        "httpStatusCode": "500",
        "errorCode": "110012",
        "description": "Invalid error description 1"
      },
      "/SOMEVALUE/BLAH.456": {
        "httpStatusCode": "500",
        "errorCode": "110013",
        "description": "Invalid error description 2"
      }
    },
    "BadErrorMappings": {
      "/SOMEVALUE/BLAH:123": {
        "httpStatusCode": "500",
        "errorCode": "110012",
        "description": "Invalid error description 1"
      },
      "/SOMEVALUE/BLAH:456": {
        "httpStatusCode": "500",
        "errorCode": "110013",
        "description": "Invalid error description 2"
      }
    }
  }
}

输出:

代码语言:javascript
复制
GoodErrorMappings: {
  "/SOMEVALUE/BLAH.123": {
    "HttpStatusCode": 500,
    "ErrorCode": 110012,
    "Description": "Invalid error description 1"
  },
  "/SOMEVALUE/BLAH.456": {
    "HttpStatusCode": 500,
    "ErrorCode": 110013,
    "Description": "Invalid error description 2"
  }
}

BadErrorMappings: {
  "/SOMEVALUE/BLAH": {
    "HttpStatusCode": 0,
    "ErrorCode": 0,
    "Description": null
  }
}
EN

回答 2

Stack Overflow用户

发布于 2016-12-21 11:59:18

发生这种情况的原因是冒号在配置绑定中具有特殊意义。

当在键字符串中提供时,冒号可用于标识集合。我在下面的示例应用程序代码更改中演示了这一点。我还更新了BadErrorMappings,使其成为绑定中的数组,因为冒号分隔符就是这样做的。

program.cs

代码语言:javascript
复制
public class Program
    {
        public static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json");

            var config = builder.Build();

            var services = new ServiceCollection().AddOptions();

            services.Configure<ApiConfig>(x => config.GetSection("ApiConfig").Bind(x));
            services.Configure<Fruit>(x => config.GetSection("Fruit").Bind(x));

            var serviceProvider = services.BuildServiceProvider();
            var apiConfig = serviceProvider.GetService<IOptions<ApiConfig>>().Value;
            var fruit = serviceProvider.GetService<IOptions<Fruit>>().Value;

            Console.WriteLine(string.Format("\r\nGoodErrorMappings: {0}", JsonConvert.SerializeObject(apiConfig.GoodErrorMappings, Formatting.Indented)));
            Console.WriteLine(string.Format("\r\nBadErrorMappings: {0}", JsonConvert.SerializeObject(apiConfig.BadErrorMappings, Formatting.Indented)));
            Console.WriteLine(string.Format("\r\nFruit: {0}", JsonConvert.SerializeObject(fruit, Formatting.Indented)));

            Console.ReadLine();
        }
    }

    public class Fruit : List<string>
    {
    }

    public class ApiConfig
    {
        public Dictionary<string, ErrorMapping> GoodErrorMappings { get; set; } = new Dictionary<string, ErrorMapping>();
        public Dictionary<string, ErrorMapping[]> BadErrorMappings { get; set; } = new Dictionary<string, ErrorMapping[]>();
    }

    public class ErrorMapping
    {
        public int HttpStatusCode { get; set; }
        public int ErrorCode { get; set; }
        public string Description { get; set; }
    }

appsettings.json

代码语言:javascript
复制
{
  "ApiConfig": {
    "GoodErrorMappings": {
      "/SOMEVALUE/BLAH.123": {
        "httpStatusCode": "500",
        "errorCode": "110012",
        "description": "Invalid error description 1"
      },
      "/SOMEVALUE/BLAH.456": {
        "httpStatusCode": "500",
        "errorCode": "110013",
        "description": "Invalid error description 2"
      }
    },
    "BadErrorMappings": {
      "/SOMEVALUE/BLAH:123": {
        "httpStatusCode": "500",
        "errorCode": "110012",
        "description": "Invalid error description 1"
      },
      "/SOMEVALUE/BLAH:456": {
        "httpStatusCode": "500",
        "errorCode": "110013",
        "description": "Invalid error description 2"
      }
    }
  },
  "Fruit:0": "Apple",
  "Fruit:1": "Orange" 
}

您也可以看到aspnet团队在他们的单元测试中利用了这一点,因此这是预定的行为。

示例:https://github.com/aspnet/Configuration/blob/dev/test/Config.Binder.Test/ConfigurationCollectionBindingTests.cs#L396-L423

票数 5
EN

Stack Overflow用户

发布于 2016-12-21 09:47:20

我找到的最简单的解决方案是将Dictionary<string, string>转换为List<KeyValuePair<string, ErrorMapping>>。然后,JSON.NET将您的列表转换为具有{ Key: 'keyname', Value: 'value' }表单的对象数组。如果您接受所需的模型更改,这将很好地工作。

使用List<KeyValuePair<string, ErrorMapping>>而不是Dictionary<string, ErrorMapping>

代码语言:javascript
复制
 public class ApiConfig
    {
        public List<KeyValuePair<string, ErrorMapping>> GoodErrorMappings { get; set; } = new List<KeyValuePair<string, ErrorMapping>>();
        public List<KeyValuePair<string, ErrorMapping>> BadErrorMappings { get; set; } = new List<KeyValuePair<string, ErrorMapping>>();
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41259476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档