动态重试代理
本文关键字:代理 重试 动态 | 更新日期: 2023-09-27 18:32:22
考虑下面,它有效:
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,但如果有其他选择呢?
城堡动态代理当然是一种选择。
但我个人会选择后锐: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()
{
}
}