Search code examples
c#genericsdelegatesfuncpolly

Wrap a method into a func


I want to create a generic wrapper around Polly framework so that can have single implementation. In order to achieve it I have written below code

    private Policy GetPolicy(EType eType)
    {
        var policy = default(Polly.Policy);

        switch (eType)
        {                

            case EType.T:
                policy = Policy.Handle<SomeException>().Retry(n, x => new TimeSpan(0, 0, x));
                break;                
        }
        return policy;
    }  

And I am using the above method in one of my wrapper methods

   public TOutput Execute<TOutput>(Func<TOutput> func, EType eType)
    {
        var policy = GetPolicy(eType);

        return policy.Execute(() => func());
    }

Now in order to consume it I have written a sample method

       var handleError = new HandleError();
        var connection = handleError.Execute(() => factory.CreateConnection(), ExceptionType.Transient);

Till above all works fine, but as soon as I start calling the same in a method which takes parameter, then it throws error as

     var handleError = new HandleError();
        handleError.Execute(() => channel.ExchangeDeclare(queueDetail.ExchangeName, ExchangeType.Fanout), ExceptionType.Transient);

     The type arguments for method 'HandleError.Execute<TOutput>(Func<TOutput>, ExceptionType)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Solution

  • You need two Execute overloads, one for functions that return value and another for those which do not:

    public TOutput Execute<TOutput>(Func<TOutput> func, ExceptionType exceptionType)
    {
        var policy = GetPolicyFromExceptionType(exceptionType);
        return policy.Execute(func);
    }
    
    public void Execute(Action action, ExceptionType exceptionType)
    {
        var policy = GetPolicyFromExceptionType(exceptionType);
        policy.Execute(action);
    }
    

    Then you can pass anything there, including functions with parameters:

    // calls first overload
    Execute(() => ImReturningValue(parameter1));
    // calls second
    Execute(() => IDoNot(parameter1));
    

    Policy.Execute method also has the same overloads (one for Func, one for Action) - so you will have no problems to pass either one to it.