繁体   English   中英

在C#中制作可重用的try / catch块的建议?

[英]Suggestions for making a reusable try/catch block in C#?

我有一个类,其中有大约20个方法。 每个人都做一些Web服务消息处理。 我只需对其进行更改,并意识到这些方法中的每一个都具有完全相同的try / catch:

        try
        {
            /* *** actual processing specific to each method goes here *** */
        }
        catch (FaultException<CustomException> cfex)
        {
            // common stuff
        }
        catch (CustomException cfex)
        {
            // common stuff
        }
        catch (Exception ex)
        {
            // common stuff
        }
        finally
        {
            FinalizeServiceCall(wsBus, wsMessage, response, logProps);
        }

我的问题是; 而不是在每个方法中都有这个完全相同的try / catch块,有没有办法让它变得常见? 我的想法是.NET有像TransactionScope这样的东西以某种方式检测离开该块时是否发生异常。 有没有我可以利用这样的东西来制作一个常见的try / catch块? 还有其他想法吗?

我会这样做:

创建一个包含try / catch的方法并将Action传递给它并在try部分中执行该操作:

public void Method1()
{
    Action action = () =>
    {
        // actual processing of Method 1
    };
    SafeExecutor(action);
}

public void Method1b()
{
    SafeExecutor(() =>
    {
        // actual processing of Method 1
    });
}

public void Method2(int someParameter)
{
    Action action = () =>
    {
        // actual processing of Method 2 with supplied parameter
        if(someParameter == 1)
        ...
    };
    SafeExecutor(action);
}

public int Method3(int someParameter)
{
    Func<int> action = () =>
    {
        // actual processing of Method 3 with supplied parameter
        if(someParameter == 1)
            return 10;
        return 0;
    };
    return SafeExecutor(action);
}

private void SafeExecutor(Action action)
{
    SafeExecutor(() => { action(); return 0; });
}

private T SafeExecutor<T>(Func<T> action)
{
    try
    {
        return action();
    }
    catch (FaultException<CustomException> cfex)
    {
        // common stuff
    }
    catch (CustomException cfex)
    {
        // common stuff
    }
    catch (Exception ex)
    {
        // common stuff
    }
    finally
    {
        FinalizeServiceCall(wsBus, wsMessage, response, logProps);
    }

    return default(T);
}

SafeExecutor的两个版本使您可以处理带有和不带返回类型的方法。
Method1b表明你不需要方法中的变量action ,如果你认为它更具可读性,你可以内联它。

有一些方法可以让你轻松完成 - 首先对我来说,我已经开始使用AOP来捕捉我的异常

这将有效地改变你的代码

try
        {
            /* *** actual processing specific to each method goes here *** */
        }
        catch (FaultException<CustomException> cfex)
        {
            // common stuff
        }
        catch (CustomException cfex)
        {
            // common stuff
        }
        catch (Exception ex)
        {
            // common stuff
        }
        finally
        {
            FinalizeServiceCall(wsBus, wsMessage, response, logProps);
        }

变成类似的东西

[HandleException( Exception , FaultException<CustomException>, 
                      "Error Getting Details" )]
    public MYType GetDetails( string parameter )
    {
        //.... call to service
    }

使用Postsharp - 详情请点击此处

另外, Mark Rendle还有一篇关于如何以函数式编程方式捕获异常的博客文章 - 尽管如此,我还没有尝试过

你已经确定了一个贯穿各领域的问题 您可以采用面向方面编程(AOP)方法来解决此问题。 这可以通过使用位于类前面的代理或在编译期间使用修改编译代码的AOP工具在运行时执行。

在过去,我已经使用Castle Dynamic Proxy来执行此操作(在运行时)。 或者,您可以使用其他AOP框架之一,如PostSharp

如果参数相同或接近相同,则始终可以传入委托。 如果它们不是你可以通过反射调用代码并使用'object []'参数传递给调用。

你可以做的是在一个方法中编写上面的代码,该方法将Action或Func作为参数来确定应该在throw块中调用的方法及其参数。

因此,如果您在throw块中调用M(1, "string") ,它将变为DoStuff(M, 1, "string")

DoStuff看起来像

void DoStuff<T1, T2, TResult>(Func<T1, T2, TResult> myMethod, T1 arg1, T2 arg2)
{
        try
        {
            myMethod(arg1, arg2)
        }
        catch (FaultException<CustomException> cfex)
        {
            // common stuff
        }
        catch (CustomException cfex)
        {
            // common stuff
        }
        catch (Exception ex)
        {
            // common stuff
        }
        finally
        {
            FinalizeServiceCall(wsBus, wsMessage, response, logProps);
        }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM