繁体   English   中英

使用反射通过字符串调用 static 方法的问题

[英]Issues with calling a static method through a string using reflection

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

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

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

上面的代码片段旨在通过其名称获取 static 方法,然后使用参数 string[] args 调用它。

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

您必须检查该命令是否不是 null。

如果你不想处理这种情况,如果不是 null,你可以简单地写:

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所见和建议的锯齿状数组[][] ,以防万一它是一个错误(应该是),如果它存在会导致执行方法中的错误。

这是高级命令行 arguments 解析的一些示例:

解析 C# 中的命令行选项

在 C# 中解析命令行 arguments 的最佳方法?

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

好吧, 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(); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM