区分.NET异常类型

时间:2010-06-08 14:59:59

标签: .net exception exception-handling

为了爱所有神圣的东西,你如何区分预定义的.NET异常类中的不同“异常风格”?

例如,一段代码可能会在以下条件下抛出XmlException

  • 文档的根元素为NULL
  • 文档中包含无效字符
  • 文件太长

所有这些都被归为XmlException个对象,所有内部“告诉我有关此异常的更多信息”字段(例如Exception.HResultException.Data等)通常都是空的或null。

这使得Exception.Message成为唯一允许您区分这些异常类型的东西,并且您无法真正依赖它,因为您猜对了,Exception.Message字符串是glocabilized的,并且文化变迁时可以改变。至少那是我对documentation的看法。

Exception.HResultException.Data在.NET库中被广泛忽略。他们是世界.NET错误处理代码的红头发儿童。即使假设它们不是,HRESULT类型仍然是错误代码历史中最糟糕,最糟糕的最糟糕的错误代码。为什么我们在2010年仍在关注HRESULTs,这超出了我的范畴。我的意思是,如果你正在做Interop或P / Invoke这是一件事,但是...... HRESULTs在System.Exception中没有位置。 HRESULTs是System.Exception的长鼻疣。

但严重的是,这意味着我必须设置许多详细的特定的错误处理代码,以便找出应该作为异常数据的一部分传递的相同信息。如果他们强迫你像这样工作,例外是没用的。我做错了什么?

EDIT。一天之后。

感谢所有评论和回复。即使我还没有完全解决具体问题,我也在这里学习一般课程(“错误消息”)。这是我正在使用的具体方案。

我们的应用程序使用第三方生成的XML文件。这些XML文件有时包含非法字符,这些字符实际上没有XML文件中的业务。这些非法字符会导致(验证)XmlReader炸毁“X行上的非法字符”异常“。但是我们必须处理这些文件;我们不能简单地告诉用户,”抱歉,该文件没有符合官方XML规范。“我们的用户甚至不知道XML是什么。

在这种情况下,Microsoft有一个官方(对我来说很奇怪)推荐(XML文档包含非法字符的情况):将文件加载到流中,迭代到包含错误的特定行(如提供的那样)具有讽刺意味的是,在XmlException对象中),并使用合法的char自定义替换有问题的char。然后尝试再次将doc加载到验证XmlReader中,看看它是否会爆炸。这是描述该技术的Knowledge Base article

很好,我们正在这样做,而且效果还不错。问题是,有时我们得到的这些XML文件在其他方面会出现格式错误:它们可能是空的,它们可能缺少结束标记等等。因此,如果您遵循MS建议,您实际上是在挂钩“替换非法字符” catch块中的逻辑,用于捕获验证读取器抛出的原始异常。

如果异常实际上是“非法char”异常,那就没问题。但是,如果它是“缺少根元素”或“缺少结束标记”异常,您会发现进入并替换有问题的char 本身的MS技术会爆炸,因为不仅没有违规行为char,根本没有chars,或者有,但是它们是无效的XML,或者其他什么。在这一点上,你是一个双重嵌套的捕捉内部捕获,你的头发变成灰色并且掉出来,你的眼睛是深红色,伴有咖啡因疲劳,你正在质疑理智,更不用说实用性了,使用验证读者对付真实世界的XML。

所以我需要的是一种告诉,在初始catch(XmlException)块中,这是一个“缺少根元素”还是“无效char”异常,所以我可以采取适当的操作。我们不能做的一件事是阻止我们的用户打开包含一些无效字符的文档。我们必须处理这些文件,我想它看起来唯一的解决方案是提前遍历文档中的每个字符,将其视为文本流而不是XML,查找非法字符,替换它们,然后使用验证的XmlReader加载该东西,如果它爆炸,我们知道是非法的char异常,因为我们事先剥离了非法的字符。

在此之前,我认为我至少要问1)我们可以从XmlException对象中获得更好的信息,我希望有人会告诉我2)“可以关闭XmlException.Message字符串。他们说它是本地化的,但事实并非如此。这个字符串在Windows的所有版本和文化中都是相同的。“

但是没有人告诉过我。

3 个答案:

答案 0 :(得分:7)

我原则上完全同意你的观点,但我真正关心抛出异常的确切原因(在我的代码中)的实例数量非常少。

以XmlException为例,如果文档太长而且代码无效,那么您的代码中会出现一些不同的行为吗?

我能想到的唯一一个我真正关心的例子是SQL类型异常,其中可以从中恢复一些错误(例如丢失的数据库连接)。

ETA:

如果您在键入错误消息时担心文化,您可以在处理文档时将当前线程文化设置为不变文化,然后在完成后将其设置回原始文化。这应该确保消息始终是相同的。

答案 1 :(得分:4)

这里的问题似乎是你从XmlException得到的糟糕信息。这是一个API设计问题。

选项使用与System.Xml不同的库,例如System.Xml.Linq,并使用XDocument查看是否获得更好的错误代码。

如果这些都不起作用,那么您可以使用开源Xml解析器,例如NDigester,并修改代码以提供更详细的错误。

答案 2 :(得分:1)

听起来需要的是XML解析例程,而不是在发生解析错误时抛出异常,而是调用传入的委托。如果委托接受与解析状态相关的信息,它可以尝试任何必要的修正,并返回一个值,指示应该重新评估文件的违规部分。

为此目的设计一个好的委托接口(一组参数和调用约定)可能很困难,但是这样的系统可以更有效地摸索通过损坏的文件而不是抛出异常的文件。

相关问题