考虑下面的内容,它起作用:
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 :(得分:0)
Castle动态代理肯定是一种选择。
但我会亲自去追查: 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()
{
}
}