I have a load of methods that throw exceptions sometimes, if they throw them I want to catch them, call a functino and then try them again a few times, here is what I am currently doing:

bool loop = true;
int i = 0;
while (loop)
{

    try
    {
        loop = false;
        if (gcDevice != null)
        {
            gcDevice.getStatus();
        }
    }
    catch (Exception e)
    {
        if (i < lisenceErrorTries)
        {
            if (e.Message == "15: license key is not valid")
            {
                System.Console.WriteLine(e.Message);
                Reconnect();
                loop = true;
            }
            else
            {
                System.Console.WriteLine(e.Message + " after " + i + " tries");
            }
        }
        else
        {
            System.Console.WriteLine(e.Message + " after " + i + " tries");
        }
        Thread.Sleep(20);
        i++;
    }
}

but the thing is, I need to do this loads and its getting really confusing writing it out all the time when all that changes is the line

gcDevice.getStatus();

what I need is something like a method where I can give it a method to perform inside the above, something like:

TryToDoThisWithRepeats(gcDevice.getStatus(), lisenceErrorTries);

Is there anything like this?

Thanks

Recommended Answers

All 7 Replies

You can use a delegate and assign it the function you want to execute.
A delegate is like a function pointer and you have probably already used them in the form of a MulticastDelegate that are used by events.
The following code snippet should explain how to use them.

class TestClass
{
    public int Value { get; set; }

    // function to be tested
    public void MyFunc()
    {
        // Do something
        Value++;
    }
}

// Define the delegate (type) for the functions you are testing.
// These need to have the same signature.
public delegate void TestFunction();

// test routine
public void RunTest(TestFunction func)
{
    for (int i = 0; i < 10; i++)
    {
        // run the test function
        func();
    }
}

private void button7_Click(object sender, EventArgs e)
{
    // create instance of class to test
    TestClass testObj = new TestClass();
    // call test routine passing function to test 
    RunTest(testObj.MyFunc);
    // show results
    MessageBox.Show(testObj.Value.ToString(), "Result=");
}
commented: Just the kind of thing I was looking for! +1

thought it was going to work :( the thing is, my functions are generally get functions, so I would have to have loads of

public delegate Class1 GetClass1 ();
public delegate Class2 GetClass2 ();
public delegate Class3 GetClass3 ();
public delegate Class4 GetClass4 ();

etc, and then loads of

public Object DoSafely(GetClass2 func)
{
   for (int i = 0; i < 10; i++)
   {
      // run the test function  (i know the loop is pointless, but imagine other stuff)
      return func();
   }
}

Ok! Solved that problem! How stupid of me to half solve it (above)

just changed:

public delegate Object GetObject();

and cast:

GCLicenseFunction function = gcDevice.GetStatus;
//gcDevice.GetStatus("2007-06-08");

Status s = (Status)PerformFunctionLicenseSafe(function);

the only problem is, how do I pass an argument with the function?

GCLicenseFunction function = gcDevice.GetStatus; has no arguments, and

GCLicenseFunction function = gcDevice.GetStatus("blablabla"); actually calls the function. I could add more arguments to my PerformFunctionLicenseSafe method, but that wouldnt be very durable. What if one function had a string argument and the other an int? I would have to have two PerformFunctionLicenseSafe methods - kind of defeating the point of doing all this in the fist place..

Two things here:

Are these Class1,Class2, Class3 objects in a hierarchy? Are you using Interfaces or a superclass? It might be a good idea to have the method return the most concise type possible, as it's more type-safe. If your classes all do have a common set of operations or properties? Then you should have them all conform to an interface.

As far as an argument to a delegate is concerned, you just declare it with a variable:

public delegate void TestFunction(string myArg);

public void ThisIsMyDelegate(string myArg)
{
     //do something
}

TestFunction myFunc = ThisIsMyDelegate; 

//call it
myFunc("some string");

Two things here:

Are these Class1,Class2, Class3 objects in a hierarchy? Are you using Interfaces or a superclass? It might be a good idea to have the method return the most concise type possible, as it's more type-safe. If your classes all do have a common set of operations or properties? Then you should have them all conform to an interface.

As far as an argument to a delegate is concerned, you just declare it with a variable:

public delegate void TestFunction(string myArg);

public void ThisIsMyDelegate(string myArg)
{
     //do something
}

TestFunction myFunc = ThisIsMyDelegate; 

//call it
myFunc("some string");

Sadly I have no control over the objects, otherwise I would make them a little hierarchy and return the most concise type as you said, they (as far as I know) dont share any properties to make an interface for, even if I could.

I'm going to mark this question as answered, because most of my functions take a string argument so making a Delegate shortens my code significantly, its just a shame you have to make a new Delegate to use it in a function with a different argument.

I think I may have come up with a solution using Delegate.CreateDelegate to create and execute the method delegate dynamically.

class TestClass
{
    public int Value { get; set; }

    // first function to be tested
    public void Increment(int inc)
    {
        // Do something
        Value += inc;
    }

    // second function to be tested
    public void Multiply(int a, int b)
    {
        Value = a * b;
    }
}

// test routine - Delegate Type, class instance, method name, parameters
public void RunTest(Type Del, object obj, string methodName, object[] args)
{
    // create delegate and execute method on instance provided
    Delegate.CreateDelegate(Del, obj, methodName).DynamicInvoke(args);
}

private void button7_Click(object sender, EventArgs e)
{
    // create instance of class to test
    TestClass testObj = new TestClass();
    // set initial value
    testObj.Value = 10;

    // call test routine passing function 1 with parameter
    RunTest(typeof(Action<int>), testObj, "Increment", new object[] { 4 });
    // show results
    MessageBox.Show(testObj.Value.ToString(), "Increment Result=");

    // call test routine again passing function 2 with parameter
    RunTest(typeof(Action<int, int>), testObj, "Multiply", new object[] { 4, 6 });
    // show results
    MessageBox.Show(testObj.Value.ToString(), "Multiply Result=");
}

Note: There is no error checking in this snippet.

I took a deeper look at delegates and found the lambda expressions.
This is another snippet that I think does what you want.

class TestClass
        {
            public double Value { get; set; }

            // method with one argument
            public void Convert(string value)
            {
                Value = System.Convert.ToDouble(value);
            }

            // method with multiple arguments of same type
            public void Multiply(double a, double b)
            {
                Value = a * b;
            }

            // method with multiple arguments of differing types
            public void Power(double value , string power)
            {

                Value = System.Math.Pow(value, System.Convert.ToDouble(power));
            }
        }

        /// <summary>
        /// Test Routine
        /// </summary>
        /// <typeparam name="T">Type of argument for caller method.</typeparam>
        /// <param name="methodCaller">Test method caller delegate.</param>
        /// <param name="args">Parameter for test method.</param>
        public void RunTest<T>(Action<T> methodCaller, T args)
        {
            // do stuff before
            methodCaller(args);
            // do stuff after
        }

        private void button7_Click(object sender, EventArgs e)
        {
            // create instance of class to test
            TestClass testObj = new TestClass();

            // call test routine passing function with single parameter
            // use a lambda expression to define the method caller delegate
            // this creates an anonymous method that is called in RunTest
            // the method body is the bit after the =>
            // the method parameter(s) are the bit before the =>
            RunTest<string>(arg => testObj.Convert(arg), "37.5");
            // show results
            MessageBox.Show(testObj.Value.ToString(), "Convert Result=");

            // call test routine passing method caller and parameter list
            // this time use an array to pass in a parameter list
            RunTest<double[]>(args => testObj.Multiply(args[0], args[1]), new double[] { 4.0, 6.0 });
            // show results
            MessageBox.Show(testObj.Value.ToString(), "Multiply Result=");

            // call test routine passing method caller and parameter list
            // this time use an array to pass in a parameter list, casting to required type
            RunTest<object[]>(args => testObj.Power((double)args[0], (string)args[1]), new object[] { 2.0, "4" });
            // show results
            MessageBox.Show(testObj.Value.ToString(), "Power Result=");
        }

Let me know what you think.
[Edit]There are also Func<> built-in delegates that takes two (or more) types, one for the output type, the other(s) for the parameter(s).
It should not be too hard to modify the above code to use Func<Tin,Tout> instead of Action<T>.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.