包装服务调用以在WCF中进行常见错误处理和跟踪

时间:2010-10-19 08:01:51

标签: c# .net wcf

有没有人为服务调用提供常见错误处理的好例子?我刚开始一个新项目,我看到很多重复的代码,我不喜欢并且想要摆脱它。我设法在其他几个层中这样做,但在代理层中调用服务它有点困难。代码的基本结构如下:

   ResponseType MyProxyFunc(different, parameters)
   {
      var client = MyServiceClient();
      using (Tracer functionTracer = new Tracer(Constants.TraceLog))
      {
          try
          {
             var response = client.MyRequest(different, parameters);
                if (response.ErrorCode != Constants.OK)
                {
                   ProxyCommon.ThrowError(besvarelseDS.Status[0].ErrorCode);
                }
          }
          finally
          {
             ProxyCommon.CloseWcfClient(client);
          }
          return response;
       }
   }

上面的代码只是一个示例,ProxyCommon对象是一个带有各种方法的静态类(应该不是抽象而不是静态,但这是另一个讨论)。那么有人有一个很好的建议如何抽象这段代码?我想在某些抽象方法中使用using,try / catch和if-statment,但由于MyServiceClient不同,参数数量不同而且请求不同,所以很难。

编辑:我之前使用的模式是使用Execute这样的通用public T Execute<T>(Func<T> func)函数。但在这种情况下我无法使用那种类型的模式。

编辑#2:我已经更新了代码,但我不是100%满意,更像是60-75%。下面的代码的问题是它使用服务对象,它们对于所有服务都不一样,但是这对于具有包装请求和响应对象的示例中的服务的服务调用是可行的,这是可以的。但我仍然认为这不是解决问题的方法:

public IList<PGSA.Data.Cargo.PGSAReportCargo> GetPGSAReport(DateTime dateFrom, DateTime? dateTo)
{
    var reportService = new ReportServiceClient();
    var request = new GetPGSAReportRequest()
    {
        SystemCode = Settings.SystemID,
        FromDate = dateFrom,
        ToDate = dateTo
    };
    var response = Execute(reportService, reportService.GetPGSAReport, request);
    return response.PGSAReport.ToList();
}

public L Execute<T, K, L>(T client, Func<K, L> serviceFunc, K request) 
    where T : ICommunicationObject
    where K : RequestBase
    where L : ResponseBase
{
    using (Tracer functionTracer = new Tracer(Constants.TraceLog))
    {
        try
        {
            L response = serviceFunc(request);
            if (response.ErrorCode != Constants.OK)
            {
                ProxyCommon.ThrowError(response.ErrorCode);
            }
            return response;
        }
        finally
        {
            ProxyCommon.CloseWcfClient(client);
        }
    }
}

编辑#3:编辑#2中的ResponseBaseRequestBase是服务定义的基类。

1 个答案:

答案 0 :(得分:1)

你的最后一种方法对我来说很好 - 我会略微简化如下:

public R Execute<T, R>(this T client, Func<R> serviceFunc) 
    where T : ICommunicationObject
    where L : ResponseBase
{
    using (Tracer functionTracer = new Tracer(Constants.TraceLog))
    {
        try
        {
            R response = serviceFunc();
            if (response.ErrorCode != Constants.OK)
            {
                ProxyCommon.ThrowError(response.ErrorCode);
            }
            return response;
        }
        finally
        {
            ProxyCommon.CloseWcfClient(client);
        }
    }
}

并使用它

reportService.Execute(() => reportService.GetPGSAReport(request));

这里的想法是消除对不需要的请求对象的依赖。