我使用Polly .NET通过重试行为包装我的方法。 Polly让它变得非常轻松和优雅,但我试图将它提升到一个新的水平。
请看这个Python示例(可能没有什么错误,但这不是重点):
class Program
{
static void Main(string[] args)
{
var someClassInstance = new SomeClass();
someClassInstance.DoSomething();
}
}
class Retry : Attribute
{
private static readonly Policy DefaultRetryPolicy = Policy
.Handle<Exception>()
.WaitAndRetry(3, retryAttempt => TimeSpan.FromSeconds(5));
public void Wrapper(Action action)
{
DefaultRetryPolicy.Execute(action);
}
}
class SomeClass
{
[Retry]
public void DoSomething()
{
// core logic
}
}
编写如上代码的好处:
由于两者没有混合 - 在我看来它使代码更具可读性。
我想使用属性在C#上使用Polly实现此语法。 我对C#属性知之甚少,对于我所读过的内容,似乎这是不可能的。
我很乐意有这样的事情:
[Retry]
正如您所看到的,在我的示例中,$shift = 6;
$array = array_combine(range($shift, count($array)+$shift-1), $array);
属性使用重试逻辑包装DoSomething方法。
如果可能的话,我将非常乐意学习如何实现它。
非常感谢您的帮助!
答案 0 :(得分:1)
当然,这是可能的。但是,它比Python更复杂。与Python不同,其中装饰器是可以交换装饰对象的可执行代码,C#中的属性是纯元数据。 .NET属性无法访问他们正在装饰的对象,而是代表自己。
因此,您必须自己连接属性和方法,尤其是自己替换方法(即使用包含重试等功能的核心逻辑替换函数)。后者在C#中是不可能隐含的,你必须明确地这样做。
它应该与此类似:
class RetryExecutor
{
public static void Call(Action action)
{
var attribute = action.Method.GetCustomAttribute(typeof(Retry));
if (attribute != null)
{
((Retry)attribute).Wrap(action);
}
else
{
action();
}
}
}