簡體   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