关于在C#中创建可重用的try/catch块的建议?
我有一个类,其中有大约20个方法。每一个都进行一些web服务消息处理。我只需要对其进行更改,并意识到这些方法中的每一种都有完全相同的try/catch:关于在C#中创建可重用的try/catch块的建议?,c#,.net,exception-handling,try-catch,C#,.net,Exception Handling,Try Catch,我有一个类,其中有大约20个方法。每一个都进行一些web服务消息处理。我只需要对其进行更改,并意识到这些方法中的每一种都有完全相同的try/catch: try { /* *** actual processing specific to each method goes here *** */ } catch (FaultException<CustomException> cfex)
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);
}
试试看
{
/****每种方法的实际处理如下****/
}
捕获(故障异常cfex)
{
//普通的东西
}
捕获(自定义异常cfex)
{
//普通的东西
}
捕获(例外情况除外)
{
//普通的东西
}
最后
{
FinalizeServiceCall(wsBus、wsMessage、response、logProps);
}
我的问题是,;有没有办法让每个方法都有完全相同的try/catch块?我的想法是.NET有类似于
TransactionScope
的东西,它可以在离开该块时检测是否发生异常。有没有我可以利用这样的东西来制作一个普通的try/catch块?还有其他想法吗?如果参数相同或接近相同,则始终可以传入代理。如果不是,您可以通过反射调用代码,并将参数“object[]”传递给invoke 我会这样做:
创建一个包含try/catch的方法,并向其中传递一个操作
,然后在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);
}
公共作废方法1()
{
动作动作=()=>
{
//方法1的实际处理
};
安全执行人(行动);
}
公开无效方法1b()
{
安全执行器(()=>
{
//方法1的实际处理
});
}
公共void方法2(int-someParameter)
{
动作动作=()=>
{
//使用提供的参数实际处理方法2
if(someParameter==1)
...
};
安全执行人(行动);
}
公共int方法3(int-someParameter)
{
Func action=()=>
{
//使用提供的参数实际处理方法3
if(someParameter==1)
返回10;
返回0;
};
返回安全执行人(行动);
}
私人无效安全执行人(行动)
{
安全执行器(()=>{action();返回0;});
}
私人安全执行人(职能行动)
{
尝试
{
返回动作();
}
捕获(故障异常cfex)
{
//普通的东西
}
捕获(自定义异常cfex)
{
//普通的东西
}
捕获(例外情况除外)
{
//普通的东西
}
最后
{
FinalizeServiceCall(wsBus、wsMessage、response、logProps);
}
返回默认值(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);
}
试试看
{
/****每种方法的实际处理如下****/
}
捕获(故障异常cfex)
{
//普通的东西
}
捕获(自定义异常cfex)
{
//普通的东西
}
捕获(例外情况除外)
{
//普通的东西
}
最后
{
FinalizeServiceCall(wsBus、wsMessage、response、logProps);
}
变成
[HandleException( Exception , FaultException<CustomException>,
"Error Getting Details" )]
public MYType GetDetails( string parameter )
{
//.... call to service
}
[HandleException(异常、故障异常、,
“获取详细信息时出错”)]
公共MYType GetDetails(字符串参数)
{
//…呼叫服务
}
使用Postsharp-
或者有一篇关于的博文-我还没有尝试过这篇博文,但是你可以在一个方法中编写上面的代码,该方法将一个动作或Func作为一个参数,该参数决定了在抛出块中应该调用的方法及其参数 因此,如果在抛出块中调用
M(1,“string”)
,它将变成DoStuff(M,1,“string”)
多斯塔夫看起来像
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);
}
}
void DoStuff(Func myMethod,T1 arg1,T2 arg2)
{
尝试
{
myMethod(arg1、arg2)
}
捕获(故障异常cfex)
{
//普通的东西
}
捕获(自定义异常cfex)
{
//普通的东西
}
捕获(例外情况除外)
{
//普通的东西
}
最后
{
FinalizeServiceCall(wsBus、wsMessage、response、logProps);
}
}
您已经确定了一个交叉问题。您可以使用面向方面编程(AOP)方法来解决这个问题。这可以在运行时通过使用位于类前面的代理来执行,也可以在编译期间通过使用修改编译代码的AOP工具来执行
在过去,我已经利用了来做这件事(在运行时)。或者,如果调用了
Complete()
,您可以使用其他AOP框架之一,例如。TransactionScope
在其Dispose()
方法中可能看起来像是(我猜Complete()
将标志设置为true
,并且Dipose()
如果是true,则提交,否则则回滚)。为什么不将try/catch逻辑提升一个级别呢?@Cody-我想将其提升一个级别,但这些方法都是WCF[OperationContract]服务方法,因此实际上没有更高的级别,除非我创建一个。@Etienne-你是对的,它检查Dispose中的完整方法。我知道这一点,但当我问这个问题时,我完全忘记了:)为什么您的WCF实现会捕获错误异常?这正是我创建的。G