Welcome back to my series on using AspectMap – an aspect oriented framework for StructureMap. If you’re new then take a look at the earlier posts on the subject:

In this post I’ll walk you through the setup of a generic exception handler which can be assigned to any code you like with the addition of a single attribute. Let’s get started!

Keeping it generic, the first thing we’ll create is a new interface for handling any exception:

public interface IExceptionHandler
{
  void HandleException(Exception ex);
}

You can create your own implementation of this which can do anything you like, log to Elmah, redirect to an error web page, send an email, whatever. Next we will create a new AttributeHandler called ExceptionAttributeHandler:

public class ExceptionAttributeHandler : AttributeHandler
{
  public ExceptionAttributeHandler(IExceptionHandler exceptionHandler)
  {
    ExceptionHandler = exceptionHandler;
  }

  public IExceptionHandler ExceptionHandler { get; set; }

  public override Action<IInvocation> Surround(Action<IInvocation> invocation,
    Attribute sourceAttribute)
  {
    throw new NotImplementedException();
  }
}

Notice the ExceptionHandler attribute and constructor, which allows us to inject our custom handler via StructureMap. Next, in the Surround method, replace the NotImplementedException with:

return i =>
{
   try
  {
    invocation(i);
  }
  catch (Exception ex)
  {
    ExceptionHandler.HandleException(ex);
    throw;
  }
};

This is just like we did with the LoggingHandler except that this time we’re nesting the invocation call within other code, and farming out the actual logic of what happens when an exception occurs to our custom IExceptionHandler class. After handling the exception, we continue to throw it.

Which is a problem.

Think about it, let’s say you are logging to Elmah and are quite happy to have the application fail after the error is logged. You will get the error logged at every point down your call stack where this aspect is applied, for a single error. We’ll fix this by creating a new HandledException class:

public class HandledException : Exception
{
  public HandledException(Exception innerException) :
    base(innerException.Message, innerException)
  {}
}

And checking the exception type in the catch block of the Surround method:

catch (Exception ex)
{
  if (!(ex is HandledException))
  {
    ExceptionHandler.HandleException(ex);
    throw new HandledException(ex);
  }
  throw;
}

Great, now you’ll handle the exception once, and get a HandledException raised by the application.

All we need to do now is create an attribute to use for the mapping:

public class ExceptionHandleAttribute : Attribute
{}

That is all the handler setup done, but we still need to wire it up to your application. Ensure that your registry inherits from AspectsRegistry and add the following lines, replacing the items in capitals with your own classes:

ForAspect<ExceptionHandleAttribute>().HandleWith<ExceptionAttributeHandler>();
For<IExceptionHandler>().Use<YOUREXCEPTIONHANDLER>();

For<IYOURCLASS>().Use<YOURCLASS>().EnrichWith(AddAspectsTo<IYOURCLASS>);

Now any methods you mark with the ExceptionHandle attribute in YOURCLASS will be automatically handled for you by your IExceptionHandler implementation.

Next time I’ll cover either a code security handler which will go into inspecting the attribute which triggered the handler code, or how to nest and prioritise multiple handlers. If you want one before the other, leave me a message in the comments and I’ll get to it. All the handlers I’m creating here will be included out of the box in a new AspectMap release some point soon too.