使用标准try / catch包装对类的方法的调用

我有一个有大约200多个方法的类,这些方法中的每一个都调用数据库或网络资源。

理想情况下,我想将每个调用包装在try / catch中,以捕获任何常见的网络或SQLexception,并让用户有机会再次尝试(如果适用)。 但是,将此代码添加到每个调用将非常耗时,并且就代码而言是膨胀的。

我已经考虑过在另一个方法中包装每个方法调用,创建一个委托,并将委托代码包装在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(Func 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代码。

在这里查看示例

希望这可以帮助。