Один короткий ответ заключается в использовании (анонимных) методов делегата с общим кодом обработки при вызове делегата.
Справочная информация: Если вы нацелились на слабые стороны или имеете код обработки ошибок, который необходимо применять повсеместно для конкретного класса проблем, и вы не хотите писать тот же файл try..catch для каждое местоположение вызова (например, обновление определенного элемента управления на каждой странице и т. д.).
Тематическое исследование: Точка боли - это веб-формы и сохранение данных в базе данных. У нас есть элемент управления, который отображает сохраненный статус для пользователя, и мы хотели иметь общий код обработки ошибок, а также общий дисплей без копирования-повторного использования на каждой странице. Кроме того, каждая страница сделала свою собственную вещь по-своему, поэтому единственной действительно общей частью кода была обработка и отображение ошибок.
Теперь, прежде чем захлопнуться, это не заменяет уровень доступа к данным и код доступа к данным. Это все еще предполагается, что существует, хорошее разделение n-уровня и т. Д. Этот код является специфичным для пользовательского интерфейса, что позволяет нам писать чистый код пользовательского интерфейса и не повторяться. Мы очень верим в исключения, но не исключаем, что некоторые исключения не требуют, чтобы пользователь получал общую страницу ошибок и терял работу. Там будет SQL таймауты, серверы идут вниз, тупиков и т.д.
Решение: То, как мы сделали это должно было пройти анонимный делегат метода на таможенного контроля и по существу вводят блок TRY с помощью анонимных делегатов ,
// normal form code.
private void Save()
{
// you can do stuff before and after. normal scoping rules apply
saveControl.InvokeSave(
delegate
{
// everywhere the save control is used, this code is different
// but the class of errors and the stage we are catching them at
// is the same
DataContext.SomeStoredProcedure();
DataContext.SomeOtherStoredProcedure();
DataContext.SubmitChanges();
});
}
Сам SaveControl имеет метод, как:
public delegate void SaveControlDelegate();
public void InvokeSave(SaveControlDelegate saveControlDelegate)
{
// I've changed the code from our code.
// You'll have to make up your own logic.
// this just gives an idea of common handling.
retryButton.Visible = false;
try
{
saveControlDelegate.Invoke();
}
catch (SqlTimeoutException ex)
{
// perform other logic here.
statusLabel.Text = "The server took too long to respond.";
retryButton.Visible = true;
LogSqlTimeoutOnSave(ex);
}
// catch other exceptions as necessary. i.e.
// detect deadlocks
catch (Exception ex)
{
statusLabel.Text = "An unknown Error occurred";
LogGenericExceptionOnSave(ex);
}
SetSavedStatus();
}
- Есть другие способы достижения этого (например, общий базовый класс, intefaces), но в нашем случае это имел наиболее подходящий.
- Это не замена отличного инструмента, такого как Elmah для регистрации всех необработанных исключений. Это целенаправленный подход к обработке определенных исключений стандартным образом.
Разве это не лечение симптомов, а не причина? то есть не следует ли вам рассматривать причину таймаутов SQL, запустив трассировку SQL Profiler на сервере базы данных? – 2008-11-17 14:58:14
Я думаю, вам нужно уточнить, что вы подразумеваете под «поймать»: как в попытке ..catch, где вы можете обрабатывать исключение, или если вы просто хотите получить информацию о необработанном исключении, и запишите где/когда (например, ELMAH) – 2009-07-29 06:05:04