2010-01-11 4 views
4

.NET에서 예외를 catch 할 때 필요한만큼 많은 유형별 예외 블록을 가질 수 있습니다. 하지만 일반적으로 적어도 하나의 "일반"예외 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 ex System.ServiceModel.FaultException"에서 "예외"를 조사하고 예외의 기본 "실제"유형을 얻고 싶습니다. 유형 (주로 디버깅 용이므로 다른 catch 블록) 또는 문자열 (로깅 용).

그러나 캐치 블록 안에는 "ex"가 이미 부모 클래스에 캐스팅되어 있으므로 원래 예외에 대한 원래 속성과 정보가 손실 된 것 같습니다.

제안 사항?

답변

13

Exception는 부모 클래스로 캐스팅되었다하더라도, 당신은 아직도 (내 C# 사면)의 기본이되는 구체적인 유형을 얻기 위해 GetType를 호출 할 수

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 's) 응답에 무엇이 문제가 있습니까? –

0

일반 시스템 예외로 catch하고 "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

+0

여전히 작동하는 경우 다른 인스턴스를 중앙에 기록하기 위해 여러 예외 유형을 반복하는 메서드에 "ex"를 전달하면 이것이 유용 할 것입니다. –

+0

나는 항상 특정 예외를 잡아 적절하게 처리하지만,이 설정을 사용하여 메소드 서명에서 일반 ex를 가져 와서 스택을 반사적으로 기록하거나 어딘가에 이메일로 보내기 위해 "오류 로거"및 "오류 전자 메일 프로그램"을 구축했습니다. if 문은 x, y 및 z를 제외한 모든 유형을 기록/이메일로 보내려고 할 때 작동합니다. –

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 
이것의 장점은 당신이 코드를 처리하는 많은 프로그램을 통해 처리 할 예외 타입의 광범위한 범위를 가질 수 있지만, 당신이 할 수 있다는 것입니다

그들을 모두 한 곳에서 처리하십시오.

나는이 답글이이 질문에 조금 늦다는 것을 알고 있지만, 내가 찾던 똑같은 것을 찾는 사람들을 돕기 위해 내가 공유 할 것이라고 생각했다.