Один короткий ответ заключается в использовании (анонимных) методов делегата с общим кодом обработки при вызове делегата.
Справочная информация : Если вы нацелились на слабые места или у вас есть какой-то стандартный код обработки ошибок, вам необходимо универсально применять его к определенному классу проблем, и вы не хотите писать ту же попытку. .catch для каждого местоположения вызова (например, обновление определенного элемента управления на каждой странице и т. д.).
Пример из практики : болевая точка - это веб-формы и сохранение данных в базе данных. У нас есть элемент управления, который отображает сохраненный статус для пользователя, и мы хотели, чтобы на каждой странице был общий код обработки ошибок, а также общее отображение без повторного копирования-вставки-повторного использования. Кроме того, каждая страница по-своему выполняла свои функции, поэтому единственной действительно распространенной частью кода была обработка ошибок и отображение.
Теперь, до того, как сработали, это не заменит слой доступа к данным и код доступа к данным. Это все еще предполагается, что существует хорошее разделение по уровням и т. Д. Этот код специфичен для уровня пользовательского интерфейса, что позволяет нам писать чистый код пользовательского интерфейса и не повторяться. Мы убеждены в том, что не нужно отменять исключения, но некоторые исключения не должны требовать, чтобы пользователь получил страницу с общей ошибкой и потерял свою работу. Будет время ожидания 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();
}
- Есть и другие способы достижения этого (например, общий базовый класс, интерфейсы), но в нашем случае это было наилучшим образом.
- Это не замена замечательному инструменту, такому как Elmah , для регистрации всех необработанных исключений. Это целенаправленный подход к обработке определенных исключений стандартным способом.