.NET:缺少必需的配置设置时会抛出哪个异常?


123

这是一个标准方案:

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

问题是,我不确定 SomeStandardException应该是哪个例外。

我仔细研究了3.5 Framework,发现了两个可能的候选对象: ConfigurationExceptionConfigurationErrorsException

System.Configuration.ConfigurationException

发生配置系统错误时引发的异常。

备注

ConfigurationException如果应用程序试图读取或写入数据到配置文件,但不成功则抛出异常。造成这种情况的一些可能原因包括配置文件中的XML格式错误,文件权限问题以及带有无效值的配置属性。

注意:

ConfigurationException维护该对象是为了向后兼容。该ConfigurationErrorsException 对象将其替换为配置系统。

实际上,此异常听起来很适合我的需要,但已被标记为过时,因此,ixthay on atthay。

这使我们深感困惑ConfigurationErrorsException

System.Configuration.ConfigurationErrorsException

当前值不是EnableSessionState值之一。

如您所见,其文档完全没有用。(在本地和在线帮助中都是这种方式。)对课程本身的检查表明,这对于我想要的内容来说是过分的杀伤力。

简而言之,我需要在应用程序配置设置丢失或包含无效值时引发的标准异常。您可能认为框架中有这样的异常供应用程序使用。(它确实做到了,但已被标记为过时,并被很多东西所取代。范围较大。)

你们使用什么解决方案(如果有的话),我是否将不得不吸收它并为此提出自己的例外?

编辑附录

有人问我是否可以提供默认值,然后继续。在某些情况下,是的,在这些情况下,不会引发异常。但是,对于某些设置,这将不适用。例如:数据库服务器名称和凭据,身份验证服务器以及已安装的第三方应用程序的路径。

还值得注意的是,我主要处理的应用程序是以批处理模式运行的控制台应用程序,并且我希望它引发一个异常,该异常会被main方法捕获并在未正确配置的情况下正确记录。(这是我继承的旧版代码,目前仅假设所有内容都是桃花心的。)


Answers:


36

您不仅可以将异常抛出限制为框架中的现有异常。如果您决定使用现有的例外,则不必一定要遵循文档中的说明。该文档将描述框架如何使用给定的异常,但并不意味着选择如何使用/重用现有异常。

它是您的应用程序-只要您对其进行记录并明确指出在缺少配置值的特定情况下将引发的异常,则可以使用任何您喜欢的异常。如果确实想要非常具体的指示缺失值,则可以考虑编写自己的ConfigurationSettingMissing异常:

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

编辑:在这种情况下编写您自己的异常会带来额外的好处,即可以确保不会对异常来自何处(框架或应用程序)造成任何混淆。该框架永远不会抛出您的自定义异常。

更新:我同意这些意见,因此我已将子类从Exception更改为ConfigurationErrorsException。我认为在可能的情况下,从现有Framework异常中继承自定义异常通常是一个好主意,避免使用Exception类,除非您需要特定于应用程序的异常。


17
我有些不同意。如果您要使用现有的异常,则应按文档中所说明的那样完全使用该异常,否则您将使那些继您之后的人感到困惑。如果您要执行其他操作,则只需创建自己的异常即可,就像您说的那样。
罗伯特·巴特

1
我不同意。除非您有捕获自定义异常的方案,否则在配置错误的情况下不太可能,最好重用现有的Type(ConfigurationErrorsException)。而且,如果您确实创建了自定义类型,则可以从诸如ConfigurationErrorsException之类的相关类型中派生它。

@Robert&Joe-我不建议现有的Framework异常应与其预期功能不一致地使用,只要有一定的灵活性即可,只要特定的情况(缺少值)适合一般情况(ConfigurationErrorsException)即可。
Dave Swersky 09年

1
如果在ASP.NET应用程序内将异常抛出为ConfigurationErrorsException,并且派生自该类的类未在受保护的OnError方法或全局ASAX Error事件中捕获,则可能会有麻烦。看到我发布的这个问题。... stackoverflow.com/questions/25299325/…–
Mick

48

就个人而言,我将使用InvalidOperationException,因为这是对象状态的问题,而不是配置系统的问题。毕竟,您是否不应该通过代码而不是配置来设置这些设置?这里的重要部分不是app.config中没有行,而是没有所需的信息。

对我而言,ConfigurationException(及其替代品ConfigurationErrorsException-尽管MSDN文档具有误导性)是用于保存,读取等配置错误。


我选择了InvalidOperationException,因为它是由ASP.NET Page保护的OnError方法处理的,而ConfigurationErrorsException及其派生的所有异常都不是
Mick

2
如果我得到一个错误的配置,如果我收到一个InvalidOperationException,这会让我感到惊讶。
keuleJ

18

正如Daniel Richardson所说,ConfigurationErrorsException是要使用的一种。通常,仅建议您创建自己的自定义Exception类型,如果您有处理它们的方案。对于通常是致命的配置错误,这种情况很少发生,因此重用现有ConfigurationErrorsException类型通常更为合适。

在.NET 2.0之前,建议使用System.Configuration.ConfigurationException。.NET 2.0中的ConfigurationException变得过时了,原因我一直不了解,因此建议改为使用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
        )
        );
}


7

ConfigurationErrorsException是您所描述情况的正确例外。对于MSDN文档的早期版本,ConfigurationErrorsException它更有意义。

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

早期的MSDN摘要和说明为:

  • 发生配置系统错误时引发的异常。
  • ConfigurationErrorsException 当在配置信息正被读出或写入发生任何错误则抛出异常。

7
来自文档:“此API支持产品基础结构,不能直接在您的代码中使用。初始化ConfigurationErrorsException类的新实例。”
Oleg Sh

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)); }

1

我会自己吸一口气,然后自己动手...但是在您这样做之前,是否可以让系统采用此配置设置的默认值?我通常会尝试对可能会丢失op 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
}

2
MSDN:...一个需要创建自己的异常的应用程序,从Exception类派生自定义异常。最初认为自定义异常应该从ApplicationException类派生。然而,在实践中,尚未发现这可以增加重大价值。
加斯珀·纳吉

是的,我认为这是因为对框架进行编码的MS程序员从ApplicationException派生了许多CLR异常,从而破坏了区分的重要性。尽管如此,我仍然这样做,因为我认为其中没有害处……
Charles Bretana

1

您可以用于配置文件的另一种方法是使用自定义配置部分,而不是AppSettings。这样,您可以指定属性IsRequired和配置系统将为您处理此检查。如果缺少该属性,它将抛出一个,ConfigurationErrorsException因此我想支持这样的答案:您应该在这种情况下使用该异常。


0

我的一般规则是:

  1. 如果缺少配置的情况不是很常见,并且我相信我永远不会与其他异常以不同的方式处理这种情况,那么我只使用基本的“ Exception”类,并附上一条适当的消息:

    抛出新的异常(“我的消息在这里”)

  2. 如果我确实想要,或者认为我极有可能以不同于大多数其他例外的方式来处理此案件,那么我会按照人们在这里已经提出的建议来提出自己的建议。


0

我倾向于不同意你提出这个问题的前提:

简而言之,我需要一个标准异常,该异常应在应用程序配置设置丢失或包含无效值时引发。您可能认为框架中有这样的异常供应用程序使用。(它显然做到了,但已被标记为过时,并被范围更大的东西所取代。)

根据有关System.Exception的MSDN文档(Exception Class,出于性能原因,您真的不应该为用户输入错误引发异常(这已由Stack Overflow和其他地方的其他人指出)。好-如果用户输入不正确,然后让应用程序正常退出,为什么函数不能返回false?这似乎更多是设计问题,而不是引发Exception的问题。

正如其他人指出的那样,如果您真的必须引发异常(无论出于何种原因),则没有任何理由无法通过继承System.Exception来定义异常类型。


2
在这种特定情况下,性能究竟为何重要?IUC,则仅将异常抛出一次,并且无论如何,此过程很可能随后会下降(当然,在向用户显示漂亮的弹出窗口之后)。(待续...)

2
返回错误代码而不是引发异常可能很痛苦,因为您必须自己将错误信息传播到调用堆栈中。对于可能在多个堆栈帧上传播的相对罕见的错误,应使用异常。两者都适用于此。

1
您错过了一些东西:“当应用程序配置设置丢失或包含无效值时”,这与错误的用户输入不同。这是缺少的基本配置。应该是自定义例外,应停止运行应用程序。
jcollum

2
在此特定应用程序中,它几乎完全由配置文件中的设置驱动。如果设置不在其中(在加密位置),则应用程序无法继续运行,必须终止。实际上需要一个例外。
Mike Hofer

1
当然,这可以涉及到语义,并且您的代码结构显然将决定您所处环境的最佳实现。尽管如此,如果您在设计中有充分的支配力,我仍然会选择一个对象来记录错误并针对异常(无论性能是否成问题)进行正常退出。
马特·乔丹

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.