У меня было странное поведение при попытке получить коллекцию в конфигурации из appsettings.json с использованием .NET 6.
Мои занятия:
public record SomeOptions
{
public IReadOnlyCollection<string> SomeColl { get; init; } = new List<string> { "wrongString" };
}
Мой appsettings.json:
{
"Some": {
"SomeColl": [ "expectedString" ]
}
}
Затем я пытаюсь получить такие значения:
var section = configuration.GetSection("Some");
var options = section.Get<SomeOptions>();
Я получил значение по умолчанию из свойства (wrongString). Но если изменить свойство следующим образом:
public record SomeOptions
{
public IReadOnlyCollection<string> SomeColl { get; init; } = null!;
}
Или
public record SomeOptions
{
public ICollection<string> SomeColl { get; init; } = new List<string>();
}
Я получил значение от appsettings.json
(expectedString). Может кто-нибудь объяснить, пожалуйста, почему это происходит?
@Magnus Магнус Это не так, потому что я хочу сделать его ненулевым. Но если у JSON пустая коллекция "SomeColl": [ ]
, она рассматривается как нулевая =(
Я не знал, что использование JsonSerializer может быть лучшей идеей, чем библиотека конфигурации.
Эта часть исходного кода описывает следующее:
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;
}
для массивов и интерфейсов, подобных спискам только для чтения, мы объединяем то, что уже есть, если можем
Хотя мне не удалось найти документального подтверждения этого.
Вы можете попробовать сообщить об этом @github, но весьма вероятно, что это не будет воспринято как критическое изменение.
Я предполагаю, что это сделано для поддержки иерархических конфигураций (т. е. когда элементы массива определены в нескольких источниках конфигурации, хотя не уверен, что это тоже хорошая идея и иногда приводит к неожиданному поведению).
Спасибо! Забыл сказать - я использую .net 6. Итак, в ConfigurationBinder
были внесены некоторые изменения. Но посмотрите, как в .net 6 логика работает аналогично - Если это тип только для чтения и уже инициализирован - верните инициализированный экземпляр, поскольку тип IS только для чтения
Разве не было бы правильно
public required IReadOnlyCollection<string> SomeColl { get; init; }
вместо присвоения ему фиктивного значения?