如何通过配置在对象上填充 IEnumerable<MyType>()?

How can I populated an IEnumerable<MyType>() on an object via configuration?

我正在尝试使用选项模式填充以下对象:

public class MyParentPolicyOptions
{
    public IEnumerable<SomePolicySettings> SomePolicySettings { get; set; }
}

我的配置 json 如下所示:

{
  "MyParentPolicy": {
     "SomePolicies": [
     {
       "Name": "Default",
       "SomeSetting": 3,
       "IsHappy": false
     },
     {
       "Name": "Custom",
       "SomeSetting": 5,
       "IsHappy": true
     }
  ]
}

对于配置我做了这样的事情:

serviceConfigurationDefinition.Optional("MyParentPolicy", Validators.MyParentPolicyOptions());

在构建配置生成器时,我可以看到它具有以下模式中预期的属性:

{[MyParentPolicy:SomePolicies:0:Name, Default}]
{[MyParentPolicy:SomePolicies:0:SomeSetting, 3}]
{[MyParentPolicy:SomePolicies:0:IsHappy, false}]

但是,在将此配置根应用到 ServiceConfigurationDefinition 之后,我的实际 MyParentPolicyOptions.SomePolicySettings 仍然为空。它似乎适用于其他强类型对象,但我无法让它适用于列表/IEnumerables/数组等。

补充一下,我刚刚用 Dictionary 尝试了这个,希望自动索引意味着这实际上是一个字典类型,但没有用。

我不知道你使用的 serviceConfigurationDefinition.Optional() 方法。一般来说,我是这样做的。你是对的 IEnumerable 正在工作。问题出在您的代码中的其他地方。以下示例正在运行。

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices( (context,services) =>
    {
        services.AddOptions();
        services.Configure<MyParentPolicy>(context.Configuration.GetSection("MyParentPolicy"));
        services.AddHostedService<Worker>();
    })
   .Build();
await host.RunAsync();

    public class MyParentPolicy
    {
        public IEnumerable<SomePolicySettings> SomePolicies { get; set; }
    }

    public class SomePolicySettings
    {
        public string Name { get; set; }
        public string SomeSetting { get; set; }
        public bool IsHappy { get; set; }  
    }

appsettings.json

{
  "MyParentPolicy": {
    "SomePolicies": [
      {
        "Name": "Default",
        "SomeSetting": 3,
        "IsHappy": false
      },
      {
        "Name": "Custom",
        "SomeSetting": 5,
        "IsHappy": true
      }
    ]
  }
}

最后检索带有 IOptionsMonitor<MyParentPolicy> 的选项,例如:

        public Worker(ILogger<Worker> logger, IOptionsMonitor<MyParentPolicy> options)
        {
            _logger = logger;
            _parentPolicyOptions = options.CurrentValue;
        }

最简单的方法是从启动配置中获取

List<SomePolicySettings> settings=  configuration.GetSection("MyParentPolicy")
.Get<MyParentPolicy>().SomePolicies.ToList();

如果您想在您的应用内的任何地方使用它,您可以创建一个服务

启动

services.Configure<MyParentPolicy>(configuration.GetSection("MyParentPolicy"));
services.AddSingleton<SomePolicySettingsService>();

服务class

public class SomePolicySettingsService
{
    private readonly  List<SomePolicySettings> _somePolicySettings;

    public SomePolicySettingsService(IOptions<MyParentPolicy> myParentPolicy)
    {
         _somePolicySettings  = myParentPolicy.Value.SomePolicies;
    }
    
    public SomePolicySettings GetDefaultPolicySettings()
    {
        return _somePolicySettings.FirstOrDefault(i=>i.Name=="Default");
    }
    public SomePolicySettings GetCustomPolicySettings()
    {
        return _somePolicySettings.FirstOrDefault(i => i.Name == "Custom");
    }
}

或者不创建和注入服务,你可以直接注入 “IOptions myParentPolicy”在您需要的任何地方的构造函数中。