I have a WCF service which logs any exceptions and then throws them as FaultExceptions.
I am doing a lot of repetition e.g. in each service method.
try {
// do some work
}
catch(Exception ex)
{
Logger.log(ex);
// actually will be Fault Exception but you get the idea.
throw ex;
}
I am looking for a more elegant way to do this as I am cutting and pasting the try/catch throughout each service.
Is there a design pattern /C# trick that could be used to make this more elegant?
You're talking about AOP -
Aspect Oriented Programming
Here's how I do it by passing the "work" as a lambda:
Then to use it:
There are other ways to achieve the same goal, and even some commercial products, but I find this way to be the most explicit and flexible.
For example, you can write an aspect that creates and disposes the client for you:
and so:
And then, you can wrap all the aspects you normally want to apply and create one master aspect.
Template method pattern is doing just this and you can easily implement it without inheritence using C#'s delegates (or lambdas).
You could also try to subscribe to the
Application_Error
event in yourglobal.asax
file.For desktop applications there is an
UnhandledException
event in theAppDomain
.Generally speaking, you could write some exception handlers that does the redundant job for you:
For WCF specific, you might look into adding own ErrorHandler. This allows you to "inject" your own code to be executed each time any method throws an exception.
You can set it up like this:
This also allows you to throw all kinds of exceptions and converting them to Fault Exceptions, which are properly handled by WCF later on, without modifying your business layer or applying try/catch code and converting them there.
If you simply throw, so propagate exception on top of the calling stack, you can avoid of handling it on every deep level, just catch it on top most (possible) level and log. Remember that
Exception
object contains stack-trace too.If you, by the way, need catching, on every level, remember use
throw
, so call stack will not be affected, instead in a way you use it, it will.