Reputation: 3942
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?
Upvotes: 2
Views: 922
Reputation: 4004
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);
}
Upvotes: 1
Reputation: 817
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);
}
Upvotes: 0
Reputation: 11319
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.";
}
}
Upvotes: 3