c# - 如何在方法调用周围添加常用功能?

标签 c# lambda dry

有问题的代码是由机器人(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/

相关文章:

c# - 在方法/数据成员中对 WCF 添加限制

c# - 使用 EPPlus 创建后下载 Excel 文件

c# - 确定何时将 lambda 编译为实例方法

java - 如何从 Java 8 流中抛出 CHECKED 异常?

delphi - 具有相同祖先的类的重复代码

c# - 使用 Entity Framework CF 迁移添加记录

c# - Redis 用 'QUEUED' 回复所有查询

function - Scala中有lambda函数吗?

go - 如何组合两个仅参数类型不同的函数

c++ - 如何避免重复发送消息