.NET: какое исключение нужно бросить, когда требуемая настройка конфигурации отсутствует?

Здесь стандартный сценарий:

if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
   throw new SomeStandardException("Application not configured correctly, bozo.");

Проблема в том, что я не совсем уверен, какое исключение должно быть SomeStandardException.

Я просмотрел 3.5 Framework и нашел двух вероятных кандидатов: ConfigurationException и ConfigurationErrorsException.

System.Configuration.ConfigurationException

Исключение, которое бросается, когда ошибка конфигурации системы произошло.

Примечания

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

Примечание:

Объект ConfigurationExceptionподдерживается для обратной совместимости. ConfigurationErrorsExceptionобъект заменяет его для конфигурации.

Это исключение действительно идеально подходит для того, что мне нужно, но оно было устаревшим, поэтому, ixnay at atthay.

Это подводит нас к совершенно загадочному ConfigurationErrorsException:

System.Configuration.ConfigurationErrorsException

Текущее значение не является одним из Значения EnableSessionState.

Как вы можете видеть, его документация совершенно бесполезна. (Это так и в локальной, и в онлайн-справке.) Изучение самого класса показывает, что это радикальное переполнение для того, что я хочу.

Вкратце, мне нужно стандартное исключение, которое должно быть выбрано, если отсутствует параметр конфигурации приложения или содержит недопустимое значение. Вы могли бы подумать, что в Framework есть такое исключение, испеченное в нем для использования приложениями. (По-видимому, это было сделано, но оно было устаревшим и было заменено чем-то большим по объему.)

Какие решения, если таковые имеются, вы, ребята, используете для этого, и мне придется сосать его и катить свое исключение для этого?

Изменить добавления

Некоторые спрашивают, могу ли я предоставить значение по умолчанию и продолжить. В некоторых случаях да, и в тех случаях исключение не будет выбрано. Однако для определенных настроек это не будет применяться. Например: имена и учетные данные сервера баз данных, серверы аутентификации и пути к установленным сторонним приложениям.

Также стоит отметить, что приложение, над которым я в первую очередь работаю, - это консольное приложение, работающее в пакетном режиме, и я хочу, чтобы оно выдало исключение, которое было поймано основным методом и зарегистрировано соответствующим образом, если вещь не надлежащим образом сконфигурированы. (Это унаследованный код, который я унаследовал, и в настоящее время просто принимает все персик.)

Ответ 1

Вы не ограничены в своих исключениях исключениями из существующих исключений в Framework. Если вы решите использовать существующие исключения, вам не обязательно следовать документации к письму. В документации будет описано, как инфраструктура использует данное исключение, но не подразумевает каких-либо ограничений в отношении того, как вы решите использовать/повторно использовать существующее исключение.

Это ваше приложение - пока вы его документируете и четко указываете исключение, которое будет выбрано в конкретном случае отсутствующего значения конфигурации, вы можете использовать любое исключение, которое вам нравится. Если вам требуется очень конкретное указание отсутствующего значения, вы можете подумать о создании собственного исключения ConfigurationSettingMissing:

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

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

ОБНОВЛЕНИЕ: Я согласен с комментариями, поэтому я изменил подкласс на ConfigurationErrorsException из Exception. Я думаю, что в целом хорошая идея подклассифицировать пользовательские исключения из существующих исключений Framework, где это возможно, избегая класса Exception, если вам не нужно исключение для конкретной программы.

Ответ 2

Лично я использовал InvalidOperationException, так как это проблема с состоянием объекта, а не с системой конфигурации. В конце концов, разве вы не должны позволять этим настройкам устанавливать код и не настраивать? Важная часть здесь заключается не в том, что в app.config не было строки, но в ней не было необходимой информации.

Мне, ConfigurationException (и его замена, ConfigurationErrorsException - несмотря на вводящие в заблуждение документы MSDN) относятся к ошибкам в сохранении, чтении и т.д. Конфигурации.

Ответ 3

Как сказал Дэниел Ричардсон, ConfigurationErrorsException - тот, который нужно использовать. В целом рекомендуется создавать собственные типы исключений, если у вас есть сценарий для их обработки. В случае ошибок конфигурации, которые обычно являются фатальными, это редко бывает так, поэтому обычно более целесообразно повторно использовать существующий тип ConfigurationErrorsException.

До .NET 2.0 рекомендуется использовать System.Configuration.ConfigurationException. ConfigurationException стало устаревшим в .NET 2.0 по причинам, которые мне никогда не были ясны, и рекомендация изменилась на использование ConfigurationErrorsException.

Я использую вспомогательный метод для исключения исключения, чтобы было легко изменить исключение, которое было выбрано в одном месте при переносе с .NET 1.x на 2.0 или Microsoft решила снова изменить рекомендацию:

if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
   throw CreateMissingSettingException("foobar");
}

...

private static Exception CreateMissingSettingException(string name)
{
    return new ConfigurationErrorsException(
        String.Format
        (
        CultureInfo.CurrentCulture,
        Properties.Resources.MissingConfigSetting,
        name
        )
        );
}

Ответ 5

ConfigurationErrorsException - правильное исключение, чтобы бросить в описываемую ситуацию. Более ранняя версия документации MSDN для ConfigurationErrorsException имеет больше смысла.

http://msdn.microsoft.com/en-us/library/system.configuration.configurationerrorsexception(VS.80).aspx

Более ранние сообщения и примечания MSDN:

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

Ответ 6

Класс ConfigurationElement (который является базовым классом многих связанных с конфигурацией классов, таких как ConfigurationSection) имеет метод OnRequiredPropertyNotFound (есть и другие вспомогательные методы). Вы можете позвонить им.

OnRequiredPropertyNotFound выполняется следующим образом:

protected virtual object OnRequiredPropertyNotFound(string name) {
    throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }

Ответ 7

Я бы сосал его и бросил сам... но прежде чем вы это сделаете, возможно ли, чтобы система приняла значение по умолчанию для этой настройки? Обычно я пытаюсь сделать это для каждой настройки, которая может быть пропущена, если у вас есть опыт управления операциями Ops Management... (или, возможно, я должен сказать, что для максимально возможного количества параметров - для некоторых явно не подходит, чтобы система принимала решение по умолчанию...)

вообще обычное исключение - это не много усилий... вот пример...

[Serializable]
public class MyCustomApplicationException : ApplicationException
{
    #region privates
    #endregion privates

    #region properties
    #endregion properties

    public MyCustomApplicationException (string sMessage,
        Exception innerException)
        : base(sMessage, innerException) { }
    public MyCustomApplicationException (string sMessage)
        : base(sMessage) { }
    public MyCustomApplicationException () { }

    #region Serializeable Code
    public MyCustomApplicationException (
       SerializationInfo info, StreamingContext context)
        : base(info, context) { }
    #endregion Serializeable Code
}

Ответ 8

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

Ответ 9

Мое общее правило:

  • Если ситуация с отсутствующей конфигурацией не очень распространена, и я считаю, что никогда бы не хотел обрабатывать этот случай иначе, чем другие исключения, я просто использую базовый класс "Исключение" с соответствующим сообщением:

    throw new Exception ( "мое сообщение здесь" )

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

Ответ 10

Я склонен не соглашаться с предпосылкой вашего вопроса:

Вкратце, мне нужно стандартное исключение, которое должно быть выбрано, если отсутствует параметр конфигурации приложения или содержит недопустимое значение. Вы могли бы подумать, что в Framework есть такое исключение, испеченное в нем для использования приложениями. (По-видимому, это было сделано, но оно было устаревшим и было заменено чем-то большим по объему.)

В соответствии с документацией MSDN в System.Exception(Класс исключений вы действительно не должны бросать исключения для ошибок ввода пользователя, для (что было указано другими в отношении и в других местах). Это также имеет смысл - почему ваша функция не возвращает false, если введен неверный ввод пользователя, и после этого приложение изящно выходит? похоже, скорее проблема дизайна, а проблема, с которой исключение бросает.

Как указывали другие, если вы действительно имеете, чтобы выкинуть исключение - по какой-либо причине - нет причин, по которым вы не могли бы определить свой тип исключения, наследуя от System.Exception.

Ответ 11

Вы можете попробовать наследовать исключение XML или просто использовать его.