2012-04-27 34 views
0

考虑之下,其工作原理:动态重试代理

public interface IService 
{ 
    void DoSomething(object arg); 
    void DoSomethingElse(object arg, bool anotherArg); 
    bool AndDoYetMoreStuff(object arg, object[] moreArgs); 
} 

public class Service : IService 
{ 
    public void DoSomething(object arg){} 

    public void DoSomethingElse(object arg, bool anotherArg){} 

    public bool AndDoYetMoreStuff(object arg, object[] moreArgs) 
    { 
     return true; 
    } 
} 

public class ServiceRetryProxy : IService 
{ 
    const int retryLimit = 3; 
    private readonly IService _service; 

    public ServiceRetryProxy(IService service) 
    { 
     _service = service; 
    } 

    private void RetryOnException(Action<IService> ctx) 
    { 
     ReconnectOnException(service => 
     { 
      ctx(service); 
      return new object(); 
     }); 
    } 

    private T RetryOnException<T>(Func<IService, T> ctx) 
    { 
     var counter = 0; 
     Exception lastException = null; 
     while (counter < retryLimit) 
     { 
      try 
      { 
       return ctx(_service); 
      } 
      catch (Exception ex) 
      { 
       lastException = ex; 
       counter++; 
      } 
     } 

     throw lastException; 
    } 

    public void DoSomething(object arg) 
    { 
     ReconnectOnException(x => x.DoSomething(arg)); 
    } 

    public void DoSomethingElse(object arg, bool anotherArg) 
    { 
     ReconnectOnException(x => x.DoSomethingElse(arg, anotherArg)); 
    } 

    public bool AndDoYetMoreStuff(object arg, object[] moreArgs) 
    { 
     return ReconnectOnException(x => x.AndDoYetMoreStuff(arg, moreArgs)); 
    } 
} 

的问题,这是我必须写在接口的每一个方法的代理方法。我想要一个更“动态”的解决方案,以便我可以将RetryOnException(或任何其他逻辑)应用于任何给定接口上的每个方法。我目前正在查看Castle DynamicProxy,但是如果有其他选项呢?

回答

0

城堡动态代理肯定是一种选择。

但我会亲自去postsharp: http://www.sharpcrafters.com/

我已经用它类似的情景。我创建RetryOnexceptionAspect在那里你可以指定异常的类型,重试次数以及它适用于任何方法:

[Serializable] 
public class RetryOnExceptionAspect : MethodInterceptionAspect 
{ 
    private readonly int maxRetries; 

    private readonly Type exceptionType; 

    public RetryOnExceptionAspect(int maxRetries, Type exceptionType) 
    { 
     this.maxRetries = maxRetries; 
     this.exceptionType = exceptionType; 
    } 

    public override void OnInvoke(MethodInterceptionArgs args) 
    { 
     for (int i = 0; i < maxRetries + 1; i++) 
     { 
      try 
      { 
       args.Proceed(); 
      } 
      catch (Exception e) 
      { 
       if (e.GetType() == exceptionType && i < maxRetries) 
       { 
        continue; 
       } 

       throw; 
      } 

      break; 
     } 
    } 
} 

用法,如:

public class Service : IService 
{ 
    [RetryOnExceptionAspect(5, typeof(TimeoutException)] 
    public void DoSomething() 
    { 
    } 
}