I got a strange behaviour when try to get collection in configuration from appsettings.json.
My Class:
public record SomeOptions
{
public IReadOnlyCollection<string> SomeColl { get; init; } = new List<string> { "wrongString" };
}
My appsettings.json:
{
"Some": {
"SomeColl": [ "expectedString" ]
}
}
Then I try get values like this:
var section = configuration.GetSection("Some");
var options = section.Get<SomeOptions>();
I got default value from property (wrongString). But if change property to be like:
public record SomeOptions
{
public IReadOnlyCollection<string> SomeColl { get; init; } = null!;
}
Or
public record SomeOptions
{
public ICollection<string> SomeColl { get; init; } = new List<string>();
}
I got value from appsettings.json (expectedString). Can someone explain please – why this is happenning?
>Solution :
This part of the source code covers that:
if (config.GetChildren().Any())
{
// for arrays and read-only list-like interfaces, we concatenate on to what is already there, if we can
if (type.IsArray || IsImmutableArrayCompatibleInterface(type))
{
if (!bindingPoint.IsReadOnly)
{
bindingPoint.SetValue(BindArray(type, (IEnumerable?)bindingPoint.Value, config, options));
}
// for getter-only collection properties that we can't add to, nothing more we can do
return;
}
for arrays and read-only list-like interfaces, we concatenate on to what is already there, if we can
Though I could not find this being documented.
My guess that this is done to support hierarchical configs (i.e. when array elements are defined in multiple configuration sources, though not sure that this is also a good idea).