Загрузка ConfigurationSection с обязательным дочерним элементом ConfigurationElement с помощью платформы конфигурации .Net

У меня есть консольное приложение, которое пытается загрузить CustomConfigurationSection из файла web.config.

В разделе пользовательской конфигурации есть обязательный элемент пользовательской конфигурации. Это означает, что когда я загружаю раздел конфигурации, я ожидаю увидеть исключение, если этот элемент конфигурации отсутствует в конфигурации. Проблема в том, что платформа .NET полностью игнорирует атрибут isRequired. Поэтому, когда я загружаю раздел конфигурации, я просто создаю экземпляр пользовательского элемента конфигурации и устанавливаю его в разделе конфигурации.

Мой вопрос, почему это происходит? Я хочу, чтобы метод GetSection() запускал исключение ConfigurationErrors, поскольку в конфигурации отсутствует требуемый элемент.

Вот как выглядит мой раздел конфигурации.

public class MyConfigSection : ConfigurationSection
{
    [ConfigurationProperty("MyConfigElement", IsRequired = true)]
    public MyConfigElement MyElement
    {
        get { return (MyConfigElement) this["MyConfigElement"]; }
    }
}
public class MyConfigElement : ConfigurationElement
{
    [ConfigurationProperty("MyAttribute", IsRequired = true)]
    public string MyAttribute
    {
        get { return this["MyAttribute"].ToString(); }
    }
}

Вот как я загружаю раздел конфигурации.

   class Program
    {
        public static Configuration OpenConfigFile(string configPath)
        {
            var configFile = new FileInfo(configPath);
            var vdm = new VirtualDirectoryMapping(configFile.DirectoryName, true, configFile.Name);
            var wcfm = new WebConfigurationFileMap();
            wcfm.VirtualDirectories.Add("/", vdm);
            return WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/");
        }

        static void Main(string[] args)
        {
            try{
                string path = @"C:\Users\vrybak\Desktop\Web.config";

                var configManager = OpenConfigFile(path);
                var configSection = configManager.GetSection("MyConfigSection") as MyConfigSection;

                MyConfigElement elem = configSection.MyElement;
            } catch (ConfigurationErrorsException ex){
                Console.WriteLine(ex.ToString());
            }
        }

Вот как выглядит мой файл конфигурации.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="MyConfigSection" type="configurationFrameworkTestHarness.MyConfigSection, configurationFrameworkTestHarness" />
  </configSections>

  <MyConfigSection>

  </MyConfigSection>

Странная часть заключается в том, что если я открою файл конфигурации и загружу раздел 2 раза подряд, я получу ожидаемое исключение.

var configManager = OpenConfigFile(path);
var configSection = configManager.GetSection("MyConfigSection") as MyConfigSection;
configManager = OpenConfigFile(path);
configSection = configManager.GetSection("MyConfigSection") as MyConfigSection;

Если я использую приведенный выше код, сработает исключение и сообщит мне, что требуется MyConfigElement. Вопрос в том, почему это исключение не выбрасывается в первый раз??


person Vadim Rybak    schedule 18.03.2010    source источник


Ответы (3)


Я обнаружил, что лучшим обходным путем для этого было вручную перебрать все вложенные свойства типа ConfigurationElement и проверить их самостоятельно после получения раздела. Если элемент требуется, но отсутствует в файле, я просто выбрасываю исключение ConfigurationErrorsException.

Вот мой код.

private void ProcessMissingElements(ConfigurationElement element)
{
    foreach (PropertyInformation propertyInformation in element.ElementInformation.Properties)
    {
        var complexProperty = propertyInformation.Value as ConfigurationElement;
        if (complexProperty == null) 
            continue;

        if (propertyInformation.IsRequired && !complexProperty.ElementInformation.IsPresent)
            throw new ConfigurationErrorsException("ConfigProperty: [{0}] is required but not present".FormatStr(propertyInformation.Name));
        if (!complexProperty.ElementInformation.IsPresent)
            propertyInformation.Value = null;
        else
            ProcessMissingElements(complexProperty);
    }
}
person Vadim Rybak    schedule 22.03.2010

Эрик ответил на это на форумах MS

Цитирую его ответ:

Элемент IsRequired атрибута ConfigurationPropertyAttribute не работает. при применении к дочернему объекту (производному от ConfigurationElement)

person David Gardiner    schedule 19.03.2010
comment
Я не думаю, что Эрик ответил правильно. Здесь вы можете увидеть мой ответ ему. социальный. msdn.microsoft.com/Forums/en-US/netfxbcl/thread/ - person Vadim Rybak; 19.03.2010
comment
Странно, что со второго раза получилось. Было бы интересно отладить код платформы .NET, чтобы увидеть, что происходит под капотом. -Дэйв - person David Gardiner; 22.03.2010

Вы пытались присвоить его непосредственно правильному типу переменной, то есть MyConfigSection вместо var? Это единственная разница, которую я вижу между двумя строками кода. (т.е. во второй строке var теперь имеет определенный тип).

person Jennifer Zouak    schedule 22.03.2010
comment
Использование определенного типа вместо var не имеет значения - person Vadim Rybak; 22.03.2010