c# - 如何在 C# 中动态调用具有任意签名的方法?

标签 c#

我有一个包含一些常见错误处理代码的类,我想传递要调用的方法和参数,但我不太能想出语法。我想做的事情大致是这样的:

private void InvokeHelper(Delegate method, params object[] args)
{
  bool retry = false;

  do
  {
    try
    {
      method.DynamicInvoke(args);
      retry = false;
    }
    catch (MyException ex)
    {
      retry = HandleException(ex);
    }
  } while (retry);
}

然后能够执行以下操作:

InvokeHelper(foo.MethodA, a, b, c);
InvokeHelper(foo.MethodB, x, y );

将 foo.MethodA 和 foo.MethodB 转换为 System.Delegate 时会出现编译器错误。我想出了下面的解决方法(实际上我更喜欢它,因为这样我就可以对我的方法的参数进行类型检查),但我很好奇是否有办法做我最初想做的事情?我知道我可以使用foo.GetType().GetMethod("MethodA")并援引它,但我试图避免反射(reflection)。我主要只是想了解.net中如何动态调用方法。

解决方法:

private delegate void EmptyDelegate();

private void InvokeHelper(EmptyDelegate method)
{
  bool retry = false;

  do
  {
    try
    {
      method.Invoke();
      retry = false;
    }
    catch (MyException ex)
    {
      retry = HandleException(ex);
    }
  } while (retry);
}

然后调用:

InvokeHelper(delegate() { foo.MethodA(a, b, c); });
InvokeHelper(delegate() { foo.MethodB(x, y); });

最佳答案

首先,您的签名是

private void InvokeHelper(Delegate method, params object[] args)

但是您犯了一个错误,必须将参数分组到一个数组中才能调用此方法:

InvokeHelper(foo.MethodA, new object[] { a, b, c});

parms 关键字告诉编译器为您执行此操作;你可以这样调用这个方法:

InvokeHelper(foo.MethodA, a, b, c);

其次,如果您的目标是 3.0 或更高版本,请不要使用 Delegate,而使用 Action:

private void InvokeHelper(Action method)

这样调用它:

InvokeHelper(()=> MyMethodToInvoke(a, b, c));

这只是一种总体上更好的方法。


至于为什么会遇到编译器问题,是因为 System.Delegates 讨厌我们。这是一个简单的事实。那是因为没有从方法组到委托(delegate)的隐式转换。

关于c# - 如何在 C# 中动态调用具有任意签名的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/349948/

相关文章:

c# - 将月差添加到新日期

c# - 如何检查无效的 UTF-8 字符?

c# - Blazor + MongoDb 身份 : Value cannot be null.(参数名称 'source')

c# - 在 ASP.NET 中包含 log4Net 外部配置文件的最佳实践

c# - 入账当天如何计算金额

c# - CompiledQuery 与普通 Linq SQL 生成

c# - Action 过滤器上的简单注入(inject)器属性注入(inject)

c# - 使用 C# 将数据从 SQL Server 2008 传输到 MySQL Workbench

c# - 具有静态工厂方法的 AutoMapper

c# - 我应该使用什么数据结构来表示多对一映射?