3

In the following, I need to pass nextDB to the Lambda expression in Retry:

Retry.Do(() => 
{
    string nextDB = dbList.Next();
    using (DataBaseProxy repo = new DataBaseProxy(nextDB))
    {
        return repo.DoSomething();
    }
});

How do I do that? Here is my Retry class:

public static class Retry
{
    public static void Do(
        Action action,
        int retryCount = 3)
    {
        Do<object>(() =>
        {
            action();
            return null;
        }, retryCount);
    }

    public static T Do<T>(
        Func<T> action,
        int retryCount = 3)
    {
        var exceptions = new List<Exception>();

        for (int retry = 0; retry < retryCount; retry++)
        {
            try
            {
                return action();
            }
            catch (Exception ex)
            {
                exceptions.Add(ex);
            }
        }

        throw new AggregateException(exceptions);
    }
}
2
  • @DavidG - I believe so - I still want it to execute the code in the Do block - but I want to be able to pass a string to Action Commented Dec 23, 2016 at 1:51
  • @DavidG No, I don't need to return anything. Yep - I just have one parameter. Cheers Commented Dec 23, 2016 at 2:03

1 Answer 1

6

I think you want to be using Action<T> here. For example:

public static void Do<T>(
    Action<T> action,
    T param,
    int retryCount = 3)
{
    var exceptions = new List<Exception>();

    for (int retry = 0; retry < retryCount; retry++)
    {
        try
        {
            action(param);
            return;
        }
        catch (Exception ex)
        {
            exceptions.Add(ex);
        }
    }

    throw new AggregateException(exceptions);
}

You would call this function like this:

Do(s => {
    Console.WriteLine(s);
}, "test", 3);

Based on your comments, it seems that you want to pass in multiple databases and try each one in succession until you find one that works. One simple option would be to remove to retryCount and instead pass in your array.

public static void Do<T>(
    Action<T> action,
    IEnumerable<T> items)
{
    var exceptions = new List<Exception>();

    foreach(var item in items)
    {
        try
        {
            action(item);
            return;
        }
        catch (Exception ex)
        {
            exceptions.Add(ex);
        }          
    }

    throw new AggregateException(exceptions);
}

And now you call it something like this:

Do(s => {
    Console.WriteLine(s);
}, new[] { "db1", "db2", "db3" });
Sign up to request clarification or add additional context in comments.

7 Comments

Damn, I don't think that is going to work for me as nextDB will be out of scope so I won't be able to pass it
What do you mean? What scope?
So I want it to execute everything in the Do block - however I want it to pass nextDB to Do each time it is executed
So you effectively want to pass in 3 different databases and keep running the method until one works?
So something like the second version?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.