有问题的代码是由机器人(CodeSmith)编写的,维护起来很痛苦。它看起来有点类似于:
public AddressProgramTemplate GetById(System.Int32 _id) {
try {
return Service.GetById(_id);
} catch (FaultException<ErrorInfo> ex) {
throw new ProxyServerBusinessException(ex.Detail);
} catch (FaultException) {
throw new ProxyServerBusinessException(null);
} catch (EndpointNotFoundException ex) {
throw new ProxyServerTechnicalException<EndpointNotFoundException>(ex);
} catch (CommunicationObjectFaultedException ex) {
throw new ProxyServerTechnicalException<CommunicationObjectFaultedException>(ex);
} catch (CommunicationException ex) {
throw new ProxyServerTechnicalException<CommunicationException>(ex);
} catch (ObjectDisposedException ex) {
throw new ProxyServerTechnicalException<ObjectDisposedException>(ex);
} catch (TimeoutException ex) {
throw new ProxyServerTechnicalException<TimeoutException>(ex);
}
}
正如您所猜测的,它是一个客户端 WCF 代理代码,并且对于每个服务方法(而且有很多)都会重复所有这些行。对机器人有利的事情对我来说却是一种悲哀,所以我开始重构它。首先,异常逻辑和处理委托(delegate)给微软企业库,公共(public)代码迁移到基类:
public TResult WrapServiceMethod<TResult>(Func<TResult> serviceMethod) {
TResult result = default(TResult);
try {
result = serviceMethod();
} catch (Exception ex) {
bool rethrow = ExceptionManager.HandleException(ex, ExceptionPolicyNames.ClientRequestPolicy);
if (rethrow) throw;
}
return result;
}
到目前为止一切顺利,丑陋的 try/catch 堆变成了简洁的一行:
return WrapServiceMethod<AddressProgramTemplate>(() => Service.GetById(_id));
还涵盖了一些努力和无效方法。当服务调用使用 out
参数时就会出现问题:
public void GetPeriod(AddressProgram program, out DateTime startDate, out DateTime endDate){
WrapServiceMethod(() => Service.GetPeriod(program, out startDate, out endDate));
}
导致“无法在匿名方法、lambda 表达式或查询表达式中使用 ref 或 out 参数“endDate””,我理解 why .
我理想中希望能够定义自定义运算符 block ,例如 while() 或 using(),这样我就可以编写
wrapexception { ... }
从此过上幸福的生活,但我认为这个技巧在.NET 中是不可能的。假设重写所有不带 out
参数的服务方法是最后的手段,我还有其他选择吗?
最佳答案
听起来您正在寻找面向方面的编程库,例如 PostSharp。
您可以创建异常处理程序,这些处理程序会在编译后根据您指定的规则插入到 IL 中,这些规则可以执行捕获异常、日志记录、跟踪等操作。
这样做的好处是您只需编写一次方面,即可将其应用于多个方法。这些方法不会混杂与当前特定任务无关的代码,因为方面会处理诸如异常处理之类的横切问题。
查看 http://www.sharpcrafters.com/solutions/monitoring#exception-monitoring 中的示例它展示了如何处理异常。
关于c# - 如何在方法调用周围添加常用功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4466353/