Подтвердить что ты не робот

Как я могу добавить сообщение в исключение без потери информации на С#?

У меня есть следующий код:

catch(Exception ex)
{
    throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}

Это, к сожалению, просто поглощает Исключение. Я могу исправить это, выполнив следующие действия:

catch(Exception ex)
{
    throw;
}

Но я все равно хотел бы включить специальное сообщение для справки о регистрации событий.

Как добавить это сообщение в исключение без потери какой-либо информации? (символы трассировки трассировки/отладки и т.д.)

4b9b3361

Ответ 1

Если вам просто нужно добавить информацию к исходному исключению, например, прочитанное пользователем сообщение или конкретные данные, которые будут вам полезны при отслеживании ошибки, но это не будет полезно для конечного пользователя, вы можете используйте свойство Exception Data, которое является ключом пары ключ/значение.

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

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

Например, вы можете сделать:

catch (Exception ex)
{
    ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
    throw;
}

Затем в клиентском коде вы можете проверить, существует ли UserMessage и, если да, представить его пользователю вместо Exception:

catch (Exception ex)
{
    if (ex.Data.Contains("UserMessage"))
    {
        MessageBox.Show(ex.Data["UserMessage"].ToString());
    }
    else
    {
        MessageBox.Show(ex.Message);
    }
}

Ответ 2

Это оригинальное Исключение все еще существует.

Когда вы выполняете регистрацию Exception, полученное Exception будет FatalException, которое вы сделали с вашим сообщением. Исходное исключение находится в ex.InnerException. Вы можете продолжить цикл через InnerException до тех пор, пока он не станет нулевым, чтобы получить всю информацию о трассировке стека и т.д.

Ответ 3

Короче говоря, не надо.

Я уверен, что вы могли бы найти какой-то способ обойти это с некоторым отражением, но я бы сильно предупредил вас об этом. Это противоречит оригинальному дизайну исключений в .NET. Исключения не просто помогают в регистрации, они предоставляют информацию об исходной причине сбоя приложения.

Использование первой опции обычно предпочтительнее, поскольку она поддерживает трассировку стека исходного исключения, но позволяет предоставить дополнительную информацию, обернув ее в отдельное исключение. В моем собственном коде всякий раз, когда я регистрирую исключения, моя функция ведения журнала рекурсирует через свойство InnerException, чтобы найти каждый бит полезной информации о ошибке.

Ответ 4

На всякий случай, если кому-то нужен хороший ответ. Ключ должен использовать AppDomain.CurrentDomain.FirstChanceException

Вы можете создать собственный объект с IDisposable, чтобы поместить в него всю информацию. И если возникает исключение, обработчик FirstChanceException получает эту информацию и заполняет Exception.Data.

Используйте Local Thread Storage, чтобы сделать его потокобезопасным. Затем код, который его перехватывает, получает данные и регистрирует их.

Пример:

using(MyCustomMessage.EnterToLocalStorage("Info for logging"") ) 
{ 
...code 
...exception thrown
.... FirstChanceException examines local thread storage and get "info for logging" and puts into Exception.Data. 
} 
//Dispose is called and all messages that were put into LocalStorage are removed. 
//So if exception was not thrown before then it like nothing happened.

Google AsyncDiagnosticStack для хорошего примера. https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs