【问题标题】:Issues with calling a static method through a string using reflection使用反射通过字符串调用静态方法的问题
【发布时间】:2020-11-04 21:18:26
【问题描述】:

我正在制作一个应用程序,该应用程序通过键入然后调用相应方法的命令在命令行进行交互。问题是,其中一些方法是异步的,因此,根据我所听到的,应该返回 Task 而不是 void,即使它们的返回值没有被使用(但是我正在制作的程序不需要异步我在某些方法中使用的库是异步的)。

因此,我不能使用代表字典(据我所知),因为它们是不同的类型,所以我尝试使用反射。

MethodInfo command = MethodBase.GetCurrentMethod()
    .DeclaringType
    .GetMethod(_commands[args[0]]);
command.Invoke(null, new string[][] { args });

上面的sn-p是想通过名字获取一个静态方法,然后用参数string[] args调用它。

根据我正在查看的文档以及其他 StackOverflow 答案,如果被调用的方法是静态的,则第一个参数应该为 null,但是无论如何我都会收到 NullReferenceException。为什么会这样,我该如何解决?

【问题讨论】:

  • 您检查过command 不为空吗?
  • _commands 是否为空?
  • GetMethod() 如果找不到您的方法,则返回 null。你确定你拼写正确吗?
  • 为什么是锯齿状 (string[][]) 数组? command?.Invoke(null, args.Select(s => (object)s).ToArray() );

标签: c# methods reflection


【解决方案1】:

您必须检查该命令是否为空。

如果你不想处理这种情况只在不为空时调用它,你可以简单地写:

command?.Invoke(null, new string[] { args });

因此,如果该方法不存在,GetCurrentMethod 返回null 并且什么都不做。

但如果您想管理案例,您需要使用测试,例如显示系统消息。

您还应该通过检查 args 是否也不是空的来强化代码。

您还应该在搜索中添加一些绑定标志。

if (args.Length == 0)
{
  Console.WriteLine("No command provided.");
  return;
}

string commandName = _commands[args[0]];

// You can remove non public or public depending on the nature of your methods
var flags = var flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;

var command = MethodBase.GetCurrentMethod().DeclaringType.GetMethod(commandName, flags);

if (command == null)
{
  Console.WriteLine("Command not found: " + commandName);
  Console.WriteLine("Allowed commands are:"
  Console.WriteLine("- ...");
  Console.WriteLine("- ...");
  return;
}

command.Invoke(null, new string[] { args });

我删除了@DmitryBychenko 所见和建议的锯齿状数组[][],以防它是一个错误(应该是),如果它存在导致执行方法中的错误。

这里有一个高级命令行参数解析的例子:

Parsing command-line options in C#

Best way to parse command line arguments in C#?

https://codereview.stackexchange.com/questions/369/parsing-console-application-arguments

https://github.com/mykeels/CommandLineParser

https://github.com/commandlineparser/commandline

https://www.codeproject.com/Articles/19869/Powerful-and-simple-command-line-parsing-in-C

【讨论】:

    【解决方案2】:

    好吧,GetMethod 可以很好地返回null 或一些非static 方法

      MethodInfo command = MethodBase
        .GetCurrentMethod()
        .DeclaringType
        .GetMethod(_commands[args[0]]);
    

    所以我们必须检查command 是否有效;由于args[0]用于查找方法,我想应该从参数中删除它(Skip(1)):

      if (command != null && command.IsStatic)
        command.Invoke(null, args.Skip(1).Cast<Object>().ToArray());
    

    请注意,如果方法可以重载(即我们有几个方法与同名),类似这样:

      MethodInfo command = MethodBase
        .GetCurrentMethod()
        .DeclaringType
        .GetMethods(BindingFlags.Public | BindingFlags.Static) 
        .Where(m => m.Name == _commands[args[0]])
        .Where(m => m.GetParameters().Length == args.Length - 1) // - 1 for Skip(1)
        .FirstOrDefault(); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-08
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多