Tagged: Exception handling

PostSharp – Exception handling

This is the first issue PostSharp helped me with – adding exception handling policies, without modifying the business code.

The example below is the one provided in the PostSharp Principles tutorial.
Based on this example, here is a quick cookbook to add exception handling:

1. PostSharp provides an abstract class for the exception handling OnExceptionAspect. Create an attribute that derives from OnExceptionAspect:

[Serializable]
public class DatabaseExceptionWrapper : OnExceptionAspect
{
    public override void OnException(MethodExecutionArgs args)
    {
        string msg = string.Format("{0} had an error @ {1}: {2}\n{3}",
            args.Method.Name, DateTime.Now,
            args.Exception.Message, args.Exception.StackTrace);

        Trace.WriteLine(msg);

        throw new Exception("There was a problem");
    }

    public override Type GetExceptionType(System.Reflection.MethodBase targetMethod)
    {
        return typeof(InvalidOperationException);
    }
}

The GetExceptionType method is called at compile time and sets the type of exception the aspect is going to handle, in this case InvalidOperationException. This method is used for writing the try/catch block that will wrap after compilation the content of the method decorated with the attribute [DatabaseExceptionWrapper].

The OnException method is called when an unhandled exception, that matches the type specified in GetExceptionType, occurs in the target method.

2. Aplying the aspect to a method:

[DatabaseExceptionWrapper]
public IQueryable GetByName(string value)
{
    var res = _contactStore.Where(c => c.FirstName.Contains(value)
                || c.LastName.Contains(value));

    if (res.Count() < 1)
    {
        ThrowNoResultsException();
    }

    Thread.Sleep(3000);
    return res.AsQueryable();
}

3. PostSharp will wrap the target method in a try/catch where the code we provided will be placed in the catch.
The result after compilation (thank you ILSpy):

public IQueryable GetByName(string value)
{
    IQueryable result;
    try
    {
      IEnumerable res =
        from c in InMemoryDataStore._contactStore
        where c.FirstName.Contains(value) || c.LastName.Contains(value)
        select c;
      if (res.Count() < 1)
      {
         this.ThrowNoResultsException();
      }
      Thread.Sleep(3000);
      IQueryable queryable = res.AsQueryable();
      result = queryable;
    }
    catch (InvalidOperationException exception)
    {
      MethodExecutionArgs methodExecutionArgs = new MethodExecutionArgs(null, null);
      MethodExecutionArgs arg_70_0 = methodExecutionArgs;
      MethodBase m = InMemoryDataStore.z__Aspects.m2;
      arg_70_0.Method = m;
      methodExecutionArgs.Exception = exception;
      InMemoryDataStore.z__Aspects.a0.OnException(methodExecutionArgs);
      throw;
    }
    return result;
}
Advertisements