使用Attributes C#包装方法

时间:2017-04-28 13:36:57

标签: c# python .net c#-4.0 attributes

我使用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方法。 如果可能的话,我将非常乐意学习如何实现它。

非常感谢您的帮助!

1 个答案:

答案 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();
        }
    }
}