将命令映射到方法

本文关键字:方法 映射 命令 | 更新日期: 2023-09-27 18:24:23

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

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});
}

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

将命令映射到方法

为什么不起作用?

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);
    }
}

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