Как избежать, чтобы исключения поймали вставку копии в.NET

Работа с платформой.NET, у меня есть сервис с рядом методов, которые могут, генерирует несколько типов исключений: MyException2, MyExc1, Исключение... Для обеспечения надлежащей работы для всех методов каждый из них содержит следующие разделы:

[WebMethod]
void Method1(...)
{
    try
    {
        ... required functionality
    }
    catch(MyException2 exc)
    {
        ... process exception of MyException2 type
    }
    catch(MyExc1 exc)
    {
        ... process exception of MyExc1 type
    }
    catch(Exception exc)
    {
        ... process exception of Exception type
    }
    ... process and return result if necessary
}

Это очень скучно, чтобы иметь точно тот же материал в КАЖДОМ сервисном методе (каждый метод имеет различный набор параметров) за точно теми же исключениями, обрабатывающими функциональность...

Там возможность состоит в том, чтобы "сгруппировать" эти разделы выгоды и использовать только одну строку (что-то подобное макросам C++)? Вероятно, что-то новое в.NET 4.0 связано с этой темой?

Спасибо.

P.S. Любые мысли приветствуются.

7
задан Budda 17 June 2010 в 22:24
поделиться

7 ответов

Если обработка исключений точно такая же во всех ваших методах, вы можете сделать что-то вроде:

void CallService(Action method)
{
    try
    {
        // Execute method
        method();
    }
    catch(MyException2 exc)
    {
        ... process exception of MyException2 type
    }
    catch(MyExc1 exc)
    {   
        ... process exception of MyExc1 type
    }
    catch(Exception exc)
    {
        ... process exception of Exception type
    }
}

Затем вы можете просто переписать свой клиентский код, чтобы он выполнял :

int i = 3;
string arg = "Foo";
this.CallService( () => this.Method1(i) );
this.CallService( () => this.Method2(arg, 5) );

Это позволяет использовать ваши методы Method1 и Method2 просто:

void Method1(int arg)
{
    // Leave out exception handling here...
    ... required functionality  
    ... process and return result if necessary
}

void Method2(string stringArg, int intArg)
{
    // Leave out exception handling here...
    ... required functionality  
    ... process and return result if necessary
}
6
ответ дан 6 December 2019 в 21:10
поделиться

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

2
ответ дан 6 December 2019 в 21:10
поделиться

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

static class ExceptionHandlerExtensionMethods 
{
    // extend to Func<T> as desired
    public static Action Catching<T>(this Action what, Action<T> handler) 
        where T : Exception
    {
        return () =>
        {
             try
             {
                 what();
             }
             catch (T ex)
             {
                 handler(ex);
             }
         };
    }
}

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

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

1
ответ дан 6 December 2019 в 21:10
поделиться

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

try
{
    ... required functionality
}
catch (Exception e)
{
    HandleException(e);
    throw; // only if you need the exception to propagate to caller
}


private void HandleException(Exception e)
{
    if (e is MyException2)
    {
        ... process exception of MyException2 type
    }
    else if (e is MyExc1)
    {
        ... process exception of MyExc1 type
    }
    else
    {
        ... process exception of Exception type
    }
}
5
ответ дан 6 December 2019 в 21:10
поделиться

Использование метода CallService от Рида Копси:

void DoSomething(object param1, int param2)
{
    this.CallService(() =>
    {
         // work with param1 and param2 here
    }
}

В случаях, когда вам нужно вернуть значение, вам может потребоваться продублировать CallService, чтобы вернуть параметр типа.

T CallService<T>(Func<T> callback) { /* ... */ }
0
ответ дан 6 December 2019 в 21:10
поделиться

Я знаю, что это плохая практика, но если у вас точно такая же обработка ошибок в каждом операторе catch, почему бы просто не использовать последний оператор catch как catch all?

Это, конечно, предполагает, что все ваши исключения наследуются от Exception.

-3
ответ дан 6 December 2019 в 21:10
поделиться

В похожей ситуации я сделал следующее. Я покажу эту технику в два этапа ...


Шаг 1. Создайте метод, который обеспечивает конкретный контекст выполнения для другого кода:

// this static method is responsible for setting up a context for other code
// to run in; specifically, it provides the exception handling "plumbing":
public static void guarded(Action action)
{                      //  ^^^^^^^^^^^^^
    try                //  actual code to be executed
    {
        action();
    }
    catch (SomeExceptionA ea)
    {
        // handle exception...
    }
    catch (SomeExceptionB eb)
    {
        // handle exception...
    }
    // etc.
}

Шаг 2. Примените этот контекст к любому фрагменту кода:

Далее , вы просто "оборачиваете" эту обработку исключений вокруг фактического кода в ваших методах:

public void MethodA()
{
    guarded(() =>   // <-- wrap the execution handlers around the following code:
    {
        // do something which might throw an exception...
    });
}

public void MethodB()
{
    guarded(() =>
    {
        // do something which might throw an exception...
    });
}

Резюме:

Общая идея здесь состоит в том, чтобы написать функцию ( guarded в приведенном выше примере), которая устанавливает конкретный контекст выполнения для выполнения другого кода. (Контекст в этом примере обеспечивает обработку исключений.) Код, который должен выполняться в этом контексте, предоставляется как лямбда-функция. Вы даже можете адаптировать функцию создания контекста, чтобы код лямбда-функции мог возвращать значение.

1
ответ дан 6 December 2019 в 21:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: