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

Вот стандартный сценарий:

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

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

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

System.Configuration.ConfigurationException

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

Замечания

The ConfigurationException exception is thrown if the application attempts to read or write data to the configuration file but is unsuccessful. Some possible reasons for this can include malformed XML in the configuration file, file permission issues, and configuration properties with values that are not valid.

Примечание.

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

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

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

System.Configuration.ConfigurationErrorsException

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

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

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

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

Редактировать дополнения

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

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


person Mike Hofer    schedule 06.01.2009    source источник
comment
Документация для System.Configuration.ConfigurationErrorsException обновлена.   -  person slolife    schedule 19.04.2018


Ответы (11)


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

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

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

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

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

person Dave Swersky    schedule 06.01.2009
comment
Я несколько не согласен. Если вы собираетесь использовать существующее исключение, его следует использовать ТОЧНО, как указано в документации, иначе вы запутаете тех, кто придет после вас. Если вы собираетесь сделать что-то другое, просто создайте собственное исключение, как вы сказали. - person Robert C. Barth; 06.01.2009
comment
Я не согласен. Если у вас нет сценария для перехвата настраиваемого исключения, что маловероятно в случае ошибки конфигурации, лучше повторно использовать существующий тип (ConfigurationErrorsException). И если вы действительно создаете настраиваемый тип, я бы унаследовал его от связанного типа, такого как ConfigurationErrorsException. - person Joe; 06.01.2009
comment
@Robert & Joe: я не предлагаю, чтобы существующие исключения Framework использовались несовместимо с их предполагаемой функцией, просто существует некоторая гибкость, если конкретный случай (отсутствующее значение) соответствует общему случаю (ConfigurationErrorsException). - person Dave Swersky; 06.01.2009
comment
С этим могут возникнуть проблемы, если вы генерируете исключение в приложении ASP.NET как ConfigurationErrorsException, а классы, производные от него, не попадают в защищенный метод OnError или событие Global ASAX Error. См. Этот вопрос, который я разместил .... stackoverflow.com/questions/25299325/ - person Mick; 14.08.2014

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

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

person Mark Brackett    schedule 06.01.2009
comment
Я выбрал InvalidOperationException, поскольку он обрабатывается методом OnError, защищенным страницей ASP.NET, в то время как исключение ConfigurationErrorsException и все производные от него исключения не - person Mick; 14.08.2014
comment
Это действительно удивит меня, если я получу исключение InvalidOperationException, если я ошибаюсь в конфигурации. - person keuleJ; 06.02.2019

Как сказал Дэниел Ричардсон, следует использовать 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
        )
        );
}
person Joe    schedule 06.01.2009

А как насчет _1 _?

person Laurent    schedule 05.05.2009
comment
ИМО, это настоящий ответ. +1 - person L C; 24.04.2018
comment
Не совсем, потому что: Предоставляет исключение для объектов SettingsProperty, которые не найдены. Что происходит от: Используется внутри как класс, представляющий метаданные об отдельном свойстве конфигурации. Это не то же самое, что отсутствующее значение конфигурации. - person Karol Haliński; 18.03.2020

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

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

Предыдущее резюме и примечания MSDN:

  • Исключение, которое выдается при возникновении ошибки системы конфигурации.
  • Исключение ConfigurationErrorsException выдается, когда возникает какая-либо ошибка во время чтения или записи информации о конфигурации.
person Daniel Richardson    schedule 06.01.2009
comment
из документации: этот API поддерживает инфраструктуру продукта и не предназначен для использования непосредственно из вашего кода. Инициализирует новый экземпляр класса ConfigurationErrorsException. - person Oleg Sh; 17.02.2016

Класс 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)); }
person Gaspar Nagy    schedule 06.01.2009

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

в общем, кастомное исключение не требует больших усилий ... вот пример ...

[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
}
person Charles Bretana    schedule 06.01.2009
comment
MSDN: ... приложение, которое должно создавать свои собственные исключения, [...] выводит настраиваемые исключения из класса Exception. Первоначально предполагалось, что настраиваемые исключения должны быть производными от класса ApplicationException; однако на практике не было обнаружено, что это дает значительную ценность. - person Gaspar Nagy; 06.01.2009
comment
Да, я думаю, это произошло потому, что программисты MS, которые кодировали фреймворк, извлекли из ApplicationException многочисленные исключения CLR, тем самым разрушив значимость различия ... Я все еще делаю это, поскольку не вижу в этом вреда ... - person Charles Bretana; 06.01.2009

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

person Yogh    schedule 08.07.2011

Мое общее правило было бы таким:

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

    выбросить новое исключение («мое сообщение здесь»)

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

person Hershi    schedule 06.01.2009

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

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

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

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

person Matt Jordan    schedule 06.01.2009
comment
Почему именно производительность будет иметь значение в этом конкретном сценарии? IUC, тогда исключение выдается ровно один раз, и процесс, вероятно, в любом случае остановится (конечно, после показа пользователю красивого всплывающего окна). (продолжение следует ...) - person ; 06.01.2009
comment
Возврат кода ошибки вместо выдачи исключения может быть болезненным, потому что тогда вам придется самостоятельно распространять информацию об ошибке вверх по стеку вызовов. Вы должны использовать исключения для относительно редких ошибок, которые могут распространяться на несколько кадров стека. Оба применимы здесь. - person ; 06.01.2009
comment
Вы что-то упустили: если параметр конфигурации приложения отсутствует или содержит недопустимое значение, это не то же самое, что неправильный ввод пользователя. Это отсутствующая базовая конфигурация. Это должно быть настраиваемое исключение, которое должно остановить запуск приложения. - person jcollum; 06.01.2009
comment
В этом конкретном приложении это почти полностью зависит от настроек в файле конфигурации. Если в нем нет настроек (где они зашифрованы), приложение не может продолжить работу и должно завершиться. Фактически требуется исключение. - person Mike Hofer; 06.01.2009
comment
Это, безусловно, может повлиять на семантику, и структура вашего кода, очевидно, будет определять лучшую реализацию для вашей ситуации. Тем не менее, если бы у вас была свобода в дизайне, я бы все равно выбрал объект для регистрации ошибки и плавный выход из исключения, независимо от того, является ли производительность проблемой или нет. - person Matt Jordan; 06.01.2009
comment
Очень хорошая статья, в которой обсуждается модель исключений .NET, на которую вы, возможно, захотите взглянуть, находится здесь: blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx Его мнение о производительности и тенденциях может оказаться полезным - и, честно говоря, оно может подтвердить или опровергнуть мои начальная точка, в зависимости от вашей ситуации. - person Matt Jordan; 06.01.2009
comment
Исключения предназначены для работы с исключительными условиями, так что это идеальное и очень подходящее использование исключений. Обычно исключения вызываются в коде внизу, затем перехватываются выше, обеспечивая плавный выход или сообщение об ошибке. Они также могут содержать данные, объясняющие, что пошло не так, или разрешающие восстановление. Исключения .NET неэффективны по сравнению с неисключительным кодом, но их использование должно быть в общем-то исключительным. - person andrewf; 16.10.2015

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

person StingyJack    schedule 06.01.2009