如何在C#中动态调用任何签名的方法?

时间:2008-12-08 15:58:11

标签: 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")并调用它,但我试图避免反思。我主要想了解如何在.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); });

2 个答案:

答案 0 :(得分:4)

首先,您的签名是

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

然而,你犯了一个错误,你必须将你的args分组成一个数组来调用这个方法:

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

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

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

其次,如果您的目标是3.0或更高版本,请不要使用委托,请使用操作:

private void InvokeHelper(Action method)

并以这种方式称呼它:

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

这只是一种更好的方法。


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

答案 1 :(得分:2)

按照Will的建议使用Action:

,这是重写
    private void InvokeHelper(Action method)
    {
        bool retry = false;

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

    public void Test()
    {
        FooClass foo = new FooClass();
        InvokeHelper( () => foo.MethodA(1, "b", 3) );
        InvokeHelper( () => foo.MethodB(2, "y"));
    }