ConfigurationBinder автоматически пропускает недопустимые элементы массива

Начиная с .NET 8, ConfigurationBinder автоматически пропускает массив и элементы списка, значения которых нельзя преобразовать в целевой тип. Ранее элементы, которые не удалось, сохранялись как заполнители null, и результирующая коллекция сохраняла ту же длину, что и количество элементов в источнике конфигурации.

Представленная версия

.NET 8

Предыдущее поведение

Ранее при привязке массива или свойства списка через Get<T>(IConfiguration) или Bind(IConfiguration, Object), если значение элемента не удалось преобразовать в целевой тип, этот элемент был сохранен в качестве null заполнителя в результате. Длина коллекции соответствовала количеству элементов в конфигурации.

// Configuration source, for example, appsettings.json:
// "Items": [
//   { "Name": "A", "Interval": 10 },
//   { "Name": "B", "Interval": "a" }   <-- invalid int
// ]

var settings = configuration.GetSection("Items").Get<MyItem[]>();

// .NET 6/7 result:
// settings.Length == 2
// settings[0] = { Name = "A", Interval = 10 }
// settings[1] = null   (conversion failed, placeholder preserved)

Новое поведение

Начиная с .NET 8 элементы, которые не выполняют преобразование типов, пропускаются автоматически. Результирующая коллекция содержит только успешно привязанные элементы и имеет более короткую длину, чем количество записей в источнике конфигурации.

var settings = configuration.GetSection("Items").Get<MyItem[]>();

// .NET 8+ result:
// settings.Length == 1
// settings[0] = { Name = "A", Interval = 10 }

Тип разрушающего изменения

Это изменение поведения.

Причина изменения

Внутренняя реализация ConfigurationBinder была рефакторингована в .NET 8. Вместо предварительного выделения целевого массива и элементов привязки на месте (которые остались null при сбое преобразования), привязыватель теперь собирает только элементы, успешно привязанные к временному списку, прежде чем материализовать окончательный массив.

Предыдущее поведение также было проблематичным для таких типов значений, как int[]. Для недопустимого значения конфигурации привязка будет хранить 0, что неотличимо от допустимого значения 0. Новое поведение избегает этой неоднозначности.

  • Включите ErrorOnUnknownConfiguration во время разработки, чтобы выявлять недопустимые значения конфигурации сразу, а не скрытно сбрасывать элементы.

    var settings = configuration.GetSection("Items").Get<MyItem[]>(options =>
        options.ErrorOnUnknownConfiguration = true);
    

    Начиная с .NET 8, этот параметр также вызывает ConfigurationBinder, чтобы выбросить InvalidOperationException, когда значение не может быть преобразовано в целевой тип. Для получения дополнительной информации см. ConfigurationBinder, который выбрасывает ошибку при несоответствии значения.

  • Исправление недопустимых значений конфигурации. Убедитесь, что все значения в источнике конфигурации соответствуют ожидаемым типам для привязанной модели.

  • Проверьте длину коллекции после привязки , если код зависит от количества элементов, соответствующих источнику конфигурации.

  • Используйте строковые свойства с ручным синтаксическим анализом, если необходимо корректно обрабатывать неподдающиеся преобразованию значения и сохранять все записи массива.

Затронутые API