开发者

Wrapping service call for common error handling and tracing in WCF

Does anyone have a good example for common error handling for service calls? I just started a new project and I see a lot of duplicate code that I don't like and would like to get rid of. I manage to do so in several other layers but in the proxy layer making the calls to services it is a little bit harder. The code is basically structured as follows:

   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;
       }
   }

The code above is just a sample, the ProxyCommon object is a static class with various methods (should probably not be abstract instead of static but that is another discussion). So does anyone have a good suggestion how to abstract this piece of code? I want to have the using, the try/catch and the if-statment in somekind of abstract method, but it's hard since MyServiceClient differs, the numbers of parameters differs and the request is not the same.

EDIT: A pattern I've used before is to use a generic Execute function like public T Execute<T>(Func<T> func). But I can't get that type of pattern to work in this case.

EDIT #2: I've updated the code but I'm not 100 % satisfied, more like 60-75 %. The problem with the code below is that it uses the service objects and they will not be the same for all services, but this will work for service calls against the service in the example that has a wrapped request and response object which it's ok. But I still don't think this is the solution to the problem:

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);
        }
    }
开发者_StackOverflow社区}

EDIT #3: The ResponseBase and RequestBase in EDIT #2 are base classes defined by the service.


Your last approach looks fine to me - I would simplify it slightly as follows:

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);
        }
    }
}

And use it

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

Idea here is to eliminate dependency on not needed request object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜