tags:

views:

53

answers:

4

I want to call a method based on a value in a lookup table. The values will be looked up in a database, and will be iterated through. What I am trying to avoid is this:

foreach (Row r in rows)
{
   if (r["command"] == "Command1")
         MyClass.Command1();
   else if (r["command"] == "Comman2")
         MyClass.Command2();
   else if (r["command"] == "Comman3")
         MyClass.Command3();
}

This is legacy code that I have to support, but I know there surely is a better way to do this. Currently the code looks like the above but I am looking for a more elegant solution.

EDIT:

Based on the suggestions below, I am trying to do something like this:

    static void Main(string[] args)
    {

        Dictionary<string, Action<MyClass>> myActions = new Dictionary<string,Action<MyClass>>();
        myActions.Add("Command1",MyClass.DoCommand1("message1"));
        myActions.Add("Command2",MyClass.DoCommand1("message2"));

        myActions["Command1"]();

    }

with my class file looking like this:

public class MyClass
{
    public void DoCommand1(string message)
    {
        Console.WriteLine(message);
    }

    public void DoCommand2(string message)
    {
        Console.WriteLine(message);
    }
}

However, I am getting syntax errors saying that an object reference is required for the nonstatic filed, method, or property MyClass.DoCommand1(string). Any ideas?

Please note I am using the .NET 2.0 framework.

+1  A: 

You can use reflection to call the method.

typeof (MyClass)
    .GetMethod((string)r["command"], BindingFlags.Static | BindingFlags.Public)
    .Invoke(null, null);
Sam
+2  A: 

You can use reflection:

string command = (string)r["command"];
typeof(MyClass)
    .GetMethod(command, BindingFlags.Static | BindingFlags.Public)
    .Invoke (null, null);

Or you can also use delegates:

var actionMap = new Dictionary<string, Action<string>> {
    {"SomeAction", MyClass.SomeAction},
    {"SomeAction2", MyClass.SomeAction2},
    {"SomeAction3", MyClass.SomeAction3},
};
actionMap[r["command"]]("SomeString");

With delegates you get a nice syntax and avoid the performance hit of reflection.

UPDATE: I noticed that you're using .NET 2.0, you need to do:

class Program
{
    delegate void PoorManAction (string param);
    static void Main(string[] args)
    {

        Dictionary<string, PoorManAction> actionMap = new Dictionary<string, PoorManAction>();
        actionMap.Add("SomeMethod1", MyClass.SomeMethod1);
        actionMap.Add("SomeMethod2", MyClass.SomeMethod2);
        actionMap.Add("SomeMethod3", MyClass.SomeMethod3);
        actionMap.Add("SomeMethod4", MyClass.SomeMethod4);
        actionMap[r["command"]]("SomeString");

    }
}

UPDATE 2:: Now the example uses methods with a string parameter as seen in the updated question

AlbertEin
I like this solution a lot, but I am not sure how to declare the delegates within Class. Can you expound upon that?
Blake Blackwell
The delegate type is Action, just declare a Dictionary<string, Action> and fill it, with YourClass.MethodName, you shouldn't need to do the delegate instantiation, the compiler should take care of that.
AlbertEin
Can you take a look at my edit above, and let me know where I'm going wrong? I'm using the .NET 2.0 framework, and I don't believe Action comes along till 3.0.
Blake Blackwell
@Blakewell i added a 2.0 equivalent solution.
AlbertEin
I feel like I'm so close! Ok, hopefully last question. Thanks for all your help btw. Is MyClass a static class, or what does the MyClass.SomeMethod1 look like? Also, can I pass parameters in?
Blake Blackwell
class MyClass { public static void SomeMethod1 () {}}You can pass parameters, but, all the methods must accept the same parameters, to do so, you need to add them to the delegates and the calling line, if you're not sure about how to do that update your questiong with the parameters needed and i'll update my answer
AlbertEin
I got it to work! Thank you very much. This will save me a lot of code, and is helping me understand delegates a little better. Again, thanks for your patience and help!
Blake Blackwell
No problem, you're welcome, i'm glad i was of some help
AlbertEin
A: 

You could use reflection to dynamically call the method. It probably would not be as efficient as a switch statement because of the overhead of using reflection.

Brad
+1  A: 

You should use anonymous delegates to produce a delegate out of a method with some (or all) arguments bound to specific values:

static void Main(string[] args)
{
    Dictionary<string, Action<MyClass>> myActions =
        new Dictionary<string,Action<MyClass>>();

    myActions.Add("Command1",
       delegate { MyClass.DoCommand1("message1"); });
    myActions.Add("Command2",
       delegate { MyClass.DoCommand1("message2"); });

    myActions["Command1"]();

}
Pavel Minaev