I'm trying to populate the following object using the Option pattern:
public class MyParentPolicyOptions
{
public IEnumerable<SomePolicySettings> SomePolicySettings { get; set; }
}
My config json looks like this:
{
"MyParentPolicy": {
"SomePolicies": [
{
"Name": "Default",
"SomeSetting": 3,
"IsHappy": false
},
{
"Name": "Custom",
"SomeSetting": 5,
"IsHappy": true
}
]
}
For the configuration I do something like this:
serviceConfigurationDefinition.Optional("MyParentPolicy", Validators.MyParentPolicyOptions());
At the point of building the configuration builder I can see it has my properties as expected in the following pattern:
{[MyParentPolicy:SomePolicies:0:Name, Default}]
{[MyParentPolicy:SomePolicies:0:SomeSetting, 3}]
{[MyParentPolicy:SomePolicies:0:IsHappy, false}]
However, after applying this configuration root to the ServiceConfigurationDefinition my actual MyParentPolicyOptions.SomePolicySettings is still null. It seems to work for other strongly typed objects but I can't get it to work for Lists / IEnumerables / arrays etc.
Just to add, I've just tried this with Dictionary<int, SomePolicySetting> in the hope that the automatic indexing would mean this was actually a dictionary type, but didn't work.
CodePudding user response:
I don't know for the serviceConfigurationDefinition.Optional()
method you use. In general I do it this way. You're right IEnumerable is working. The issue is somewhere else in your code. The following example is working.
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; }
}
and appsettings.json
:
{
"MyParentPolicy": {
"SomePolicies": [
{
"Name": "Default",
"SomeSetting": 3,
"IsHappy": false
},
{
"Name": "Custom",
"SomeSetting": 5,
"IsHappy": true
}
]
}
}
And finally retrieve the options with IOptionsMonitor<MyParentPolicy>
for example:
public Worker(ILogger<Worker> logger, IOptionsMonitor<MyParentPolicy> options)
{
_logger = logger;
_parentPolicyOptions = options.CurrentValue;
}
CodePudding user response:
The easiest way is to get it from startup configuration
List<SomePolicySettings> settings= configuration.GetSection("MyParentPolicy")
.Get<MyParentPolicy>().SomePolicies.ToList();
if you want to use it everywhere inside of your app , you can create a service
startup
services.Configure<MyParentPolicy>(configuration.GetSection("MyParentPolicy"));
services.AddSingleton<SomePolicySettingsService>();
service 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");
}
}
or instead of creating and injecting service, you can just inject " IOptions myParentPolicy" in the constructor everywhere you need.