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

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

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

我的问题是; 而不是在每个方法中都有这个完全相同的try / catch块,有没有办法让它变得常见? 我的想法是.NET有像TransactionScope这样的东西以某种方式检测离开该块时是否发生exception。 有没有我可以利用这样的东西来制作一个共同的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 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(Func action) { try { return action(); } catch (FaultException 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来捕捉我的exception

这将有效地改变你的代码

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

变成类似的东西

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

使用Postsharp – 详情请点击此处

另外, Mark Rendle还有一篇关于如何以函数式编程方式捕获exception的博客文章 – 虽然我没有尝试过这个

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

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

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

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

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

DoStuff看起来像

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