将命令映射到方法

时间:2015-11-24 19:58:34

标签: c#

我有一个命令行应用程序,我将命令映射到方法,使用单字母命令中的字典到方法名称(作为字符串)。我既可以使用这种方法来调用它,也可以告诉用户可用命令列表,如下所示:

private static readonly Dictionary<string, string> commands =
    new Dictionary<string, string>
    {
        {"u", "DestroyUniverse"},
        {"g", "DestroyGalaxy"},
        {"p", "DestroyPlanet"},
        {"t", "TimeTravel"}
    };

public void DestroyUniverse(Stack<string> argStack)
{
     // destroy the universe according to the options in argStack
     // ...
}

public void DestroyGalaxy(Stack<string> argStack)
{
     // destroy the galaxy according to the options in argStack
     // ...
}

// ... other command methods

public void Run(Stack<string> argStack)
{
    var cmd = argStack.Next();
    string methodName;

    // if no command given, or command is not found, tell
    // user the list of available commands

    if (cmd == null || !commands.TryGetValue(cmd, out methodName))
    {
        Console.WriteLine("Available Commands:{0}{1}", 
            Environment.NewLine, 
            string.Join(Environment.NewLine,
            commands.OrderBy(kv => kv.Key)
                    .Select(kv => string.Format("{0} - {1}", kv.Key, kv.Value))));

        Environment.ExitCode = 1;
        return;
    }

    // command is valid, call the method

    GetType().GetMethod(methodName).Invoke(this, new object[] {argStack});
}

这很好用,除了我不喜欢我使用字符串作为字典中的值。因此,没有编译器支持确保每个字符串都有一个方法。我宁愿以某种方式使用“方法”,但仍然可以访问方法的名称,对于我列出命令的部分。有没有这样的东西?

2 个答案:

答案 0 :(得分:3)

为什么这不起作用?

class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        p.Run(new Stack<string>(args.Reverse()));
        Console.ReadKey();
    }

    private readonly Dictionary<string, Action<Stack<string>>> commands;

    public Program() {
        commands =
            new Dictionary<string, Action<Stack<string>>>
            {
                {"u", DestroyUniverse },
                {"g", DestroyGalaxy },
                {"p", DestroyPlanet },
                {"t", TimeTravel }       
            };
     }

    public void DestroyUniverse(Stack<string> argStack)
    {
        // destroy the universe according to the options in argStack
        // ...
    }

    public void DestroyGalaxy(Stack<string> argStack)
    {
        // destroy the galaxy according to the options in argStack
        // ...
    }

    private string Next(Stack<string argStack)
    {
        // wish this was a method of Stack<T>
        return argStack.Any() ? argStack.Pop() : null;
    }

    public void Run(Stack<string> argStack)
    {
        var cmd = Next(argStack);

        Action<Stack<string>> action = null;

        // if no command given, or command is not found, tell
        // user the list of available commands
        if (cmd == null || !commands.TryGetValue(cmd, out action))
        {
            Console.WriteLine("Available Commands:{0}{1}",
                Environment.NewLine,
                string.Join(Environment.NewLine,
                    commands.OrderBy(kv => kv.Key)
                        .Select(kv => string.Format("{0} - {1}",
                             kv.Key, kv.Value.Method.Name))));
            Environment.ExitCode = 1;
            return;
        }

        // command is valid, call the method
        action(argStack);
    }
}

答案 1 :(得分:0)

您可以使用反射。获取您感兴趣的所有方法的MethodInfo并将它们放入字典中。之后你可以调用其中一个。如果您需要将方法的名称作为字符串,您也可以从MethodInfo中获取它。