繁体   English   中英

如何将 appsetting.json 部分加载到 .NET Core 中的字典中?

[英]How to load appsetting.json section into Dictionary in .NET Core?

我熟悉将 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 注入控制器?

使用这种结构格式:

"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);
});

对于其他想要将其转换为Dictionary 的人

appsettings.json 中的示例部分

"MailSettings": {
    "Server": "http://mail.mydomain.com"        
    "Port": "25",
    "From": "info@mydomain.com"
 }

以下代码应放在启动文件 > 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"];

一个缺点是所有值都将作为字符串检索,如果您尝试任何其他类型,则该值将为空。

您可以使用Configuration.Bind(settings); startup.cs类中

你的设置类会像

public class AppSettings
{
    public Dictionary<string, string> MobileConfigInfo
    {
        get;
        set;
    }
}

希望能帮助到你!

我相信您可以使用以下代码:

var config =  Configuration.GetSection("MobileConfigInfo").Get<Dictionary<string, string>>(); 

到目前为止,最简单的方法是定义您的配置类以从您想要支持的 Dictionary 类型继承。

public class MobileConfigInfo:Dictionary<string, string>{
}

那么您的启动和依赖注入支持将与任何其他配置类型完全相同。

对于简单的(也许是微服务)应用程序,您可以将其添加为单例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
}

在 .NET Core 3.1 中,您可以执行以下操作...

appsettings.json:

{
  "myConfig": {
    "foo": "bar",
    "myMappings": {
      "key1": "value1",
      "key2": "value2"
    }
  }
}

一个配置模型

配置文件

public class MyConfig
{
    public string Foo { get; set; }
    public Dictionary<string, string> MyMappings { get; set; }
}

启动.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 字典映射的方式。

唯一对我有用(ASP.NET Core 3.0)的是将以下内容添加到Startup.csConfigureServices方法中:

services.Configure<Dictionary<string, string>>(dict => Configuration
    .GetSection("MySectionName")
    .GetChildren()
    .ToList()
    .ForEach(c => dict[c.Key] = c.Value));

我用下面的方法:

appsettings.json:

  "services": {
      "user-service": "http://user-service:5000/",
      "app-service": "http://app-service:5000/"
  } 

启动.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;
}

作为 ASP.Net Core 2.1 中更复杂绑定的示例; 根据文档,我发现使用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; }
}

您可以即时完成:

appsettings.json:
{
   "MobileConfigInfo": {
      "a": "x",
      "b": "y",
      "c": "z"
    }
}

代码中的某处:(不要忘记向类构造函数添加 IConfiguration 依赖项)

var yourDictionary = _configuration.GetSection("MobileConfigInfo")
                .Get<IDictionary<string, string>>();

我有一个用于设置字典类型属性的通用解决方案,例如从选项中检索的 HTML 属性字典。

可以在选项中设置默认字典值。 如果该部分中存在相同的键,则覆盖字典中的值,否则插入键值对。

字典的类型是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> { }
}

不更改应用程序设置对我来说更好的方法:

"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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM