2010-01-11 75 views
4

在.NET中捕捉异常时,可以根据需要使用特定类型的异常块。但我通常会尝试拥有至少一个“常规”异常catch块。但有没有办法获得被泛型异常处理程序捕获的“真正”异常的类型,也许使用反射?捕捉一般异常时,如何确定原始异常类型?

举例来说,如果我有

Catch ex As System.ServiceModel.FaultException(Of InvalidUser) 
    ProcessModuleLoadException(Me, ex) 
Catch ex As System.ServiceModel.FaultException(Of SQLExceptions) 
    ProcessModuleLoadException(Me, ex) 
Catch ex As System.ServiceModel.FaultException(Of DataNullReference) 
    ProcessModuleLoadException(Me, ex) 
Catch ex As System.ServiceModel.FaultException 
    ProcessModuleLoadException(Me, ex) 
Catch ex As Exception 
    ProcessModuleLoadException(Me, ex) 

(我让他们爆发的调试,即使我做每个异常的同样的事情)。我想检查“ex”并获得基本的“真实”类型的异常,或者作为一种类型(主要是为了调试,所以我可以添加另一种类型的异常catch块)或者作为一个字符串(用于日志记录)。

但是,在Catch块内部,“ex”已经被转换为它的父类,因此任何有关原始异常的原始属性和信息似乎都会丢失。

对此提出建议?

回答

13

即使Exception已经投给它的父类,你仍然可以调用GetType获得其底层的具体类型(原谅我的C#):

try { 
    // Do stuff 
} 
catch(Exception ex) { 
    Type exceptionType = ex.GetType(); 
} 

如果这仅仅是用于诊断目的,你可以登录ex.ToString(),其包括通过默认(除了堆栈跟踪等)的基础类型是这样的:

System.ArgumentException: lastName 
    at Tests.Program.Main(String[] args) in ...\Program.cs:line 22 
+2

@downvoter:这个(和runrunraygun的)答案有什么问题? – 2011-02-12 12:57:14

0

如何捕捉它作为一个通用的系统异常,然后使用“is”术语来测试实际类型?

try 
{ 
    // Something 
} 
catch(Exception ex) 
{ 
    // Single catch block - catches as generic system exception 
    if(ex is FaultException) { 
     //Process as FaultEx 
    } 
    if(ex is ArithmeticException) { 
     //Process as ArithEx 
    } 
    if(ex is ArgumentException) { 
     //Process as ArgEx 
    } 
} 
finally 
{ 
    //Cleanup 
} 
+1

我从来没有在生产代码中看到过这样的事情,对我而言,感觉就像是一种轻微的不自然的事情,让你在大if语句中重现内置特性(多个catch块)。这种方法有什么优势吗? – gingerbreadboy 2010-01-11 21:09:36

+0

如果它仍然有效,我可以看到,如果您将“ex”传递给一个方法,然后迭代不同的异常类型以便将它们记录在中心位置,那么该方法将非常有用。 – 2010-01-12 15:16:57

+0

我总是捕获特定的异常和相应的过程,但我已经构建了“错误记录器”和“错误电子邮件程序”,它们使用此设置在方法签名中采用通用前缀,并在某处反射记录堆栈/电子邮件地址。 当我想记录/发送除x,y和z以外的所有类型的电子邮件时,if语句开始起作用。 – 2010-01-12 16:03:02

2

这只能从杰夫的答案稍作修改:

我一直在寻找的东西,像什么克里斯描述,具体我想处理原始例外,它已被少数通用再次抛出后异常,并且只有一个处理程序可供我为所有入口点调用。而且由于重新抛出一个异常会用它自己的异常类型来包装它,我们需要添加循环来检查内部异常,并检查抛出的第一个异常。

因此,这里是我结束了代码:

Public Sub HandelException(myEx As Exception) 
    Try 
     Dim InnerEx As Exception = myEx 
     Do Until InnerEx.InnerException Is Nothing 
      InnerEx = InnerEx.InnerException 
     Loop 

     If InnerEx.GetType = GetType(Exception1) Then 
      'Handle exception type 1 
     ElseIf InnerEx.GetType = GetType(Exception2) Then 
      'Handle exception type 2 
     ElseIf InnerEx.GetType = GetType(Exception3) Then 
      'Handle exception type 3 
     ElseIf InnerEx.GetType = GetType(Exception4) Then 
      'Handle exception type 4 
     ElseIf InnerEx.GetType = GetType(Exception) Then 
      'Handle generic system exception 
     End If 
    Catch ex As Exception 
     'Handel unlikely exception in exception handler LOL. 
    End Try 
End Sub 

这样做的好处是,你可以有你处理整个程序中,有很多的处理代码异常类型的范围广泛,但你可以在一个地方处理它们。

我知道这个回复对于这个问题有点迟,但是我想我会分享一下,或许是为了帮助那些寻找我正在寻找的东西的人。