При обнаружении общего исключения, как я могу определить исходный тип исключения? - PullRequest
5 голосов
/ 11 января 2010

При отлове исключения в .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)

(я разбил их для отладки, хотя я делаю одно и то же с каждым исключением).

Короче говоря, в «Catch ex As System.ServiceModel.FaultException» я хочу изучить «ex» и получить базовый «реальный» тип исключения, либо в виде типа (в основном для отладки, так что я могу добавить еще один catch блок) или в виде строки (для регистрации).

Но внутри блока Catch "ex" уже приведен к родительскому классу, поэтому любые оригинальные свойства и информация об исходном исключении, похоже, потеряны.

Предложения

Ответы [ 4 ]

15 голосов
/ 11 января 2010

Даже если 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 голосов
/ 20 апреля 2016

Это лишь небольшое изменение из ответа Джеффа:

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

Итак, вот код, с которым я закончил:

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

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

Я знаю, что этот ответ немного запоздал на этот вопрос, но я подумал, что поделюсь, если, возможно, чтобы помочь кому-то, ищущему то же, что я искал.

2 голосов
/ 11 января 2010

.GetType все равно вернет свой фактический тип.

0 голосов
/ 11 января 2010

Как насчет того, чтобы перехватить его как общее системное исключение, а затем использовать "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
} 
...