Атрибут ConfigurationIgnore в .NET 11
В Microsoft.Extensions.Configuration атрибут ConfigurationKeyNameAttribute существует с .NET 6 и позволяет переименовывать ключ, к которому привязано свойство. Но официального способа указать «не привязывать это свойство вообще» никогда не было. Этот пробел наконец-то устранён в .NET 11 с помощью ConfigurationIgnoreAttribute.
Проблема
Допустим, у вас есть класс параметров, который выглядит примерно так:
public class CsvIngestionOptions
{
// Вычисляется после загрузки – НЕ должен идти из конфигурации
public CsvFormatOptions DefaultFormat { get; set; }
// Раздел конфигурации, который мы привязываем и обрабатываем
public IConfigurationSection? DefaultFormatSection { get; set; }
// Вызывается после загрузки конфигурации, чтобы применить постобработку и значения по умолчанию
internal void OnConfigurationLoaded()
{
DefaultFormat = new CsvFormatOptions();
DefaultFormatSection?.Bind(DefaultFormat);
DefaultFormat.EnsureEncodingDefined();
}
}
DefaultFormat извлекается из DefaultFormatSection после некоторой постобработки. Его никогда не следует заполнять напрямую связывателем. Но поскольку у него есть публичные геттер и сеттер, система конфигурации пытается его связать.
Единственным обходным путём до .NET 11 было злоупотребление ConfigurationKeyNameAttribute с намеренно некорректным ключом:
// Костыль
[ConfigurationKeyName("__ignored_" + nameof(DefaultFormat))]
public CsvFormatOptions DefaultFormat { get; set; }
Это ненадёжно, вводит в заблуждение и создаёт странный код в вашей схеме конфигурации.
Решение
.NET 11 добавляет специальный атрибут ConfigurationIgnoreAttribute в Microsoft.Extensions.Configuration. Просто добавляем атрибут к тому свойству, которое не должно быть привязано:
public class CsvIngestionOptions
{
[ConfigurationIgnore]
public CsvFormatOptions DefaultFormat { get; set; }
[ConfigurationKeyName(nameof(DefaultFormat))]
public IConfigurationSection? DefaultFormatSection { get; set; }
// …
}
Ещё один распространённый сценарий
Постобработка — наиболее очевидный, но не единственный вариант использования. Ещё один классический пример — парсинг исходного значения:
public class FeatureFlags
{
public string RawFlags { get; set; } = string.Empty;
[ConfigurationIgnore]
public IReadOnlyDictionary<string, bool>
ParsedFlags { get; set; }
= new Dictionary<string, bool>();
}
Можно ли просто использовать [JsonIgnore]?
Нет, в этом и проблема. System.Text.Json.Serialization.JsonIgnoreAttribute не влияет на связыватель конфигурации.
Замечание: начиная с .NET 9, связыватель уже пропускает свойства только для чтения (только-get/только-init при отсутствии соответствующего раздела). Предлагаемый здесь атрибут предназначен для свойств, доступных для записи, которые могут быть связаны, но не должны быть связаны.
См. также обсуждение проблемы на GitHub.
Источник: https://steven-giesel.com/blogPost/18a61100-6074-43ac-86ae-573ad66a2c8a/configurationignoreattribute-in-net-11