Reusing try catch for wcf call

折月煮酒 提交于 2019-12-11 00:54:56

问题


I have a series of methods that call wcf services and all of them have the same try catch code

Response Method1(Request request)
{
    Response response = null;
    using(ChannelFactory<IService1> factory = new ChannelFactory<IService1>(myEndpoint))
    {
        IService1 channel = factory.CreateChannel();
        try
        {
            response = channel.Operation(request);
        }
        catch(CommunicationException ex)
        {
            // Handle Exception
        }
        catch(TimeoutException ex)
        {
            // Handle Exception
        }
        catch(Exception ex)
        {
            // Handle Exception
        }
    }
    return response;
}

And so on (I have 6 methods like this for different services).. how can i encapsulate all the service calls and handle the exceptions in a single method

EDIT

Following Nathan A's advice I created a simple generic method:

protected TResult ExecuteAndCatch<TResult>(Func<T, TResult> serviceCall, T request)
    where T : Request
    where TResult : Response
{
    try
    {
        return serviceCall(request);
    }
    catch (CommunicationException ex)
    {
    }
    catch (TimeoutException ex)
    {
    }
    catch (Exception ex)
    {
    }
    return null;
}

The new methods would like this

Response NewMethod1(Request request)
{
    Response response = null;
    using(ChannelFactory<IService1> factory = new ChannelFactory<IService1>(myEndpoint))
    {
        IService1 channel = factory.CreateChannel();
        response = channel.Operation(request);
    }
    return response;
}

and i'm trying to call it like

Response response = ExecuteAndCatch<Response>(NewMethod1, new Request())

What am I doing wrong?


回答1:


Use a wrapper function.

Take a look at this article: http://mytenpennies.wikidot.com/blog:writing-wcf-wrapper-and-catching-common-exceptions

Here's an example from the article:

private void ExecuteAndCatch<T> (Action<T> action, T t) {
    try {
        action (t);
        Success = true;
    }
    catch (TimeoutException) {
        Success = false;
        Message = "Timeout exception raised.";
    }
    catch (CommunicationException) {
        Success = false;
        Message = "Communication exception raised.";
    }
}



回答2:


If your client derives from ClientBase<T> e.g MyClient : ClientBase<IWCFService>

You could then create your own base class that provides methods that will wrap the common functionality.

The below sample code could be expanded to allow the final derived class to specify what to do when a particular method call fails. Here I just call HandleError

In specific client class

//method that returns a value
public int Ping()
{
    return Protect(c => c.Ping());
}    

//void method usage
public void Nothing(int stuff)
{
    Protect(c => c.Nothing(stuff));
}      

In client base class

protected void Protect(Action<IWCFService> action)
{
    Protect(c => { action(c); return true; });
}

//add other exception handling
protected Protect<T>(Func<IWCFService, T> func)
{
    try
    {
        return func(Channel);
    }
    catch (FaultException e)
    {
        HandleError(e);//up to you to implement this and any others
    }

    return default(T);
}



回答3:


inject the various clients through an interface and then run the operation in a single place?

HttpResponse performOperation(IServiceClient injectedServiceClient)
{
    IServiceClient client = injectedServiceClient;

    try
    {
        client.Operation();
    }
    catch(CommunicationException ex)
    {
        // Handle Exception
    }
    catch(TimeoutException ex)
    {
        // Handle Exception
    }
    catch(Exception ex)
    {
        // Handle Exception
    }
    return httpResponse(httpStatusCode.OK);
}


来源:https://stackoverflow.com/questions/23524280/reusing-try-catch-for-wcf-call

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!