I would use unity interface/virtualmethod interception.
_unityContainer.AddNewExtension<Interception>(); 
_unityContainer.RegisterType<ITestCaching, TestCaching>(
    new Interceptor<InterfaceInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());
_unityContainer.RegisterType<XRepository>(
    new Interceptor<VirtualMethodInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());
I use policy injection behavior so that I can use Attributes to add the additional behavior.
custom attributes involved in interception will need to inherit  HandlerAttribute
and implement:
public override ICallHandler CreateHandler(IUnityContainer container)
{
    return new RetryCallHandler(container, ConfigurationName);
}
The behavior will be implemented in the class that implements ICallHandler
public class RetryCallHandler : ICallHandler, IDisposable
{
    public IMethodReturn Invoke(IMethodInvocation args, GetNextInterceptionBehaviorDelegate getNext) 
    { 
        Exception exception = null;
        int retryCounter = MAX_RETRIES;
        do
        {
            exception = null;
            try
            {
                var intercepted = getNext();
                IMethodReturn methodReturn = intercepted(args, getNext);
                return methodReturn;
            }
            catch (Exception ex)
            {
                exception = ex;
            }
        }while(exception!=null && retryCounter-- > 0);
        return args.CreateExceptionMethodReturn(exception);
    }
}
I haven't compiled or tested the above code.
The only problems that I foresee are GetNextInterceptionBehaviorDelegate in case you have multiple interceptions.
You can manage the order of your call handlers so just make sure that this is the last in the chain.