Search code examples
c#aoppostsharp

Using PostSharp to retry method on Exception


For one of my DAL modules I have lots of duplicated plumbing in the shape of:

while (retry)
{
...
try
{
   ...do something
   retry = false;
}
catch (SqlException sqlEx)
{
   // Retry only if -2 = Connection Time Out or 1205 = Deadlock
  if (sqlEx.Number == -2 || sqlEx.Number == 1205)
  {
      ..retry if attempt < max
  }
      ..log and rethrow exception
}
}

and having discovered PostSharp recently I'm attempting to replace these plumbing code with an attribute.

My original plan was to: - extend OnMethodInvocationAspect and remember the method invocation event args during method invocation - implement IOnExceptionAspect and implement OnException to check exception type and if retry is required use the method invocation event args object from the original call, i.e.:

[Serializable]
public sealed class RetryAttribute : OnMethodInvocationAspect, IOnExceptionAspect
{
    [NonSerialized]
    private MethodInvocationEventArgs m_initialInvocationEventArgs = null;

    public override void OnInvocation(MethodInvocationEventArgs eventArgs)
    {
        if (m_initialInvocationEventArgs == null)
            m_initialInvocationEventArgs = eventArgs;

        base.OnInvocation(eventArgs);
    }

    public void OnException(MethodExecutionEventArgs eventArgs)
    {
        // check if retry is necessary
        m_initialInvocationEventArgs.Proceed();
    }
}

but the OnInvocation method is not fired anymore once I've added IOnExceptionAspect..

Does anyone know what I need to do here? Or perhaps there's more suitable aspect I should use?

Thanks,


Solution

  • You cannot have an aspect that implement two aspect interfaces (IOnMethodInvocation and IOnExceptionAspect in your case). The weaver will take one arbitrary interface and implement the aspect.

    I think all you need to achieve your objective is OnMethodInvocationAspect. Why don't you put the for loop and the try-catch in the OnInvocation handler?