views:

103

answers:

4

Hi

I have a simple .NET application which runs as Windows Service. Say it has one Class

MyClass
{
  Run(Destination d)
  Walk(Destination d)
  Wash(Dishes d)
}

I want to create a console application where I would type simple human readable commands like

run left
walk right

Pretty much like you do in windows console. I wonder what is the best way to implement this mapping. A straight methods is of course create your own string parser with lots of switch statements but I think if there is better and faster method.

+1  A: 

Perhaps a PowerShell CommandLet would be an option, although that would constrain you or your users to PowerShell (which is a superior shell IMO).

Mark Seemann
+2  A: 

You have two options here:

  1. Use reflection to find the class method with the approrpiate name and invoking it.

  2. Use the command pattern, where each command object would have a name and a Run() method. You can easily find the desired command by name, then run it.

UPDATE: Aggreed, there are more than two options (see Guffa's answer). But these two are the ones that make the code clearer IMHO.

Konamiman
+2  A: 

Not really. There are other methods, but if they are better is mostly a matter of taste, and for identifying a string you can't do it much faster than a switch.

If all method have the same parameters, you could set up a dictionary of strings and delegates.
Example:

var methods = new Dictionary<string, Action<int>>();
methods.Add("run", n => MyClass.Run(n));
methods.Add("walk", n => MyClass.Walk(n));
methods.Add("wash", n => MyClass.Wash(n));

string cmd = "run";
int param = 42;
if (methods.ContainsKey(cmd)) {
   methods[cmd](param);
} else {
  Console.WriteLine('Say what, human?');
}
Guffa
+3  A: 

This might be too much for your needs, but I think a robust, flexible way to do it would be creating a couple of meta-data attributes to decorate the classes you might want to call from your shell, something like:

[ScriptableClass]
public class MyClass
{
     [ScriptableMethod(typeof (Destination),typeof(int))]
     public void Run (Destination f, int distance) {}
}

Then, during your shell's startup, you load your assemblies via reflection and look for types marked with the ScriptableClass attribute. For each of them, you inspect their public methods looking for those marked with the ScriptableMethod attribute, and you can build a dictionary of classes and their scriptable methods (along with info about parameters). For the previous example, you would have a 'MyClass.Run' command you can could from the shell. When received, your scripting engine would create / lookup an instance of the class and execute the method.

The advantage of this method is that you wouldn't have to modify your scripting engine every time you add new classes or modify methods.

axel_c
+1, the best solution to the problem. The attribute classes and reflection code probably doesn't even take more than 20 or so lines.
erikkallen