如何避免异常捕获.NET中的复制粘贴

时间:2010-06-17 18:28:53

标签: .net asp.net exception copy-paste

使用.NET框架我有一个带有一组方法的服务,这些方法可以生成几种类型的异常:MyException2,MyExc1,Exception ...为所有方法提供适当的工作,每个方法都包含以下部分:

[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
}

在EACH服务方法中拥有完全相同的东西(每个方法都有不同的参数集),处理功能完全相同,这是非常无聊的......

是否有可能“分组”这些捕获部分并仅使用一行(类似于C ++宏)?可能.NET 4.0中的新内容与此主题有关吗?

感谢。

P.S。欢迎任何想法。

7 个答案:

答案 0 :(得分:6)

如果您的所有方法中的异常处理完全相同,您可以执行以下操作:

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
}

答案 1 :(得分:5)

为什么不将代码分解为辅助方法来为您执行此操作(您可以将以后需要的任何新异常添加到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
    }
}

答案 2 :(得分:2)

我会仔细研究你正在做什么来“处理”这些例外。您根本不需要catch块,并且您应该允许传播异常。

答案 3 :(得分:1)

突然出现了一种怪异的东西(并展示了你可以做但你最不应该也不想做的事情):你可以通过动态生成包含异常处理的函数来使整个事物更具可组合性和可重用性逻辑:

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);
             }
         };
    }
}

现在,您可以在某处实现和重用异常类型特定的处理函数,并将它们组合成其他方法的异常处理。

要删除冗余,您可以编写一个辅助函数,将“典型”异常处理函数添加到您想要调用的函数中,并调用此装饰方法。

答案 4 :(得分:1)

我在类似情况下做了以下事情。我将分两步展示这项技术......


步骤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),为其他代码设置一个特定的执行上下文。(这个例子中的上下文提供了异常处理。)要在此上下文中执行的代码作为lambda函数提供。您甚至可以调整上下文创建函数,以便lambda函数中的代码可以返回值。

答案 5 :(得分:0)

使用Reed Copsey的CallService方法:

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

对于需要返回值的情况,可能必须复制CallService才能返回类型参数。

T CallService<T>(Func<T> callback) { /* ... */ }

答案 6 :(得分:-3)

我知道这是不好的做法,但是如果你在每个catch语句中都有完全相同的错误处理,为什么不只是使用最后一个catch语句作为catch all?

这当然假设您的所有异常都从Exception继承。