Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态重试代理_C#_.net_Castle Dynamicproxy_Dynamic Proxy - Fatal编程技术网

C# 动态重试代理

C# 动态重试代理,c#,.net,castle-dynamicproxy,dynamic-proxy,C#,.net,Castle Dynamicproxy,Dynamic Proxy,请考虑以下有效的方法: 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 DoSomethi

请考虑以下有效的方法:

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));
    }
}

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

Castle dynamic proxy肯定是一个选项

但我个人会选择postsharp:

我已经在类似的场景中使用了它。我创建了RetryOneExceptionSpect,您可以在其中指定异常类型、重试次数并将其应用于任何方法:

[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()
    {
    }
}