How to load polymorphic objects in appsettings.json
The key to answer this question is to know how the keys are generated. In your case, the key / value pairs will be:
DynamicConfig:Features:0:TypeDynamicConfig:Features:0:Options:MaxFileSizeDynamicConfig:Features:1:TypeDynamicConfig:Features:1:Options:MinAgeDynamicConfig:Features:1:Options:MaxAgeDynamicConfig:Features:2:TypeDynamicConfig:Features:2:Options:MinAgeDynamicConfig:Features:2:Options:MaxAge
Notice how each element of the array is represented by DynamicConfig:Features:{i}
.
The second thing to know is that you can map any section of a configuration to an object instance, with the ConfigurationBinder.Bind
method:
var conf = new PersonCheckerOption();Configuration.GetSection($"DynamicConfig:Features:1:Options").Bind(conf);
When we put all this together, we can map your configuration to your data structure:
services.Configure<FeaturesOptions>(opts =>{ var features = new List<FeatureConfig>(); for (var i = 0; ; i++) { // read the section of the nth item of the array var root = $"DynamicConfig:Features:{i}"; // null value = the item doesn't exist in the array => exit loop var typeName = Configuration.GetValue<string>($"{root}:Type"); if (typeName == null) break; // instantiate the appropriate FeatureConfig FeatureConfig conf = typeName switch { "FileSizeChecker" => new FileSizeCheckerOptions(), "PersonChecker" => new PersonCheckerOption(), _ => throw new InvalidOperationException($"Unknown feature type {typeName}"), }; // bind the config to the instance Configuration.GetSection($"{root}:Options").Bind(conf); features.Add(conf); } opts.Features = features.ToArray();});
Note: all options must derive from FeatureConfig
for this to work (e.g. public class FileSizeCheckerOptions : FeatureConfig
). You could even use reflection to automatically detect all the options inheriting from FeatureConfig
, to avoid the switch over the type name.
Note 2: you can also map your configuration to a Dictionary
, or a dynamic
object if you prefer; see my answer to Bind netcore IConfigurationSection to a dynamic object.