簡體   English   中英

使用標准try / catch包裝對類的方法的調用

[英]Wrapping calls to method on a class with a standard try/catch

我有一個有大約200多個方法的類,這些方法中的每一個都調用數據庫或網絡資源。

理想情況下,我想將每個調用包裝在try / catch中,以捕獲任何常見的網絡或SQL異常,並讓用戶有機會再次嘗試(如果適用)。 但是,將此代碼添加到每個調用將非常耗時,並且就代碼而言是膨脹的。

我已經考慮過在另一個方法中包裝每個方法調用,創建一個委托,並將委托代碼包裝在try / catch中......就像這樣......

(忽略語法......這只是一個概念性的例子)

bool CallUpdatePassenger(int PassengerId,string PassengerName,string PhoneNumber)
{
    Delegate del= Delegate.CreateDelegate(typeof(UpdatePassengerDelegate), typeof(IPassengerServices).GetMethod("RemoteUpdatePassenger"));
    bool Res=(bool)CallDelegate(del,PassengerName,PhoneNumber);
}
object CallDelegate(Delegate del,params object[] args)
{
    object Result=null;
    try
    {
        Result=del.DynamicInvoke(args);
    }
    catch (Some.Timeout.Error.Or.Whatever te)
    {
        // take some action.. maybe retry etc.. 
    }
    return Result;
}

也許還有更實用的方法嗎?

代碼是自動生成的(通過我編寫的工具)我可以很容易地包含上面的內容,但我想避免為每個方法調用編寫上面的代碼。

此外,如果我執行上述操作,我可以計時方法,並記錄方法調用等。它看起來有點笨拙(而不是強類型)。

謝謝Rich。

你應該能夠做以下事情:

T Execute<T>(Func<T> func) {
    try {
        return func();
    } catch (...) {
        ...
    }
}
bool CallUpdatePassenger(some args here) {
    return Execute( () => realObj.RemoteUpdatePassenger(some args here));
}

或者,您可以使用元編程為動態基礎方法編寫動態“裝飾器”...但除非您熟悉ILGenerator等,否則最好不要 - 它是一個相當高級的主題。

我認為你的基本想法很好,但有一種更簡單的方法來實現它(至少你是使用.Net 3.5或更新版本):

void WithStandardRetryLogic(Action method) 
{
    try
    {
        method();
    }
    catch (Some.Timeout.Error.Or.Whatever te)     
    {         
        // take some action.. maybe retry etc..      
    } 
}

使用示例:

WithStandardRetryLogic(delegate() { CallUpdatePassenger(PassengerId, PassengerName, PhoneNumber); });

這也可能是AOP框架可能有用的東西,但我還沒有嘗試過這個解決方案。

如果您可以使用PostSharp,則可以使用以下方面:

[Serializable]
public class RetryAttribute : MethodInterceptionAspect
{
    private readonly int _times;

    public RetryAttribute(int times)
    {
        _times = times;
    }

    public override void OnInvoke(MethodInterceptionArgs args)
    {
        for (var left = _times; left > 0; left--)
        {
            try
            {
                args.Proceed();
                break;
            }
            catch (Exception)
            {
            }
        }
        args.Proceed(); // optional
    }
}

用法如下:

[Retry(2)]
public static void DoIt()
{
    Console.WriteLine("tried");
    throw new Exception();
}

我認為其中一個可能的解決方案是AOP編程。 您可以使用屬性標記所需的任何方法,並在編譯時注入try/catch代碼。

在這里查看示例

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM