Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中动态调用具有任何签名的方法?_C# - Fatal编程技术网

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

如何在C#中动态调用具有任何签名的方法?,c#,C#,我有一个类,其中包含一些常见的错误处理代码,我想传入要调用的方法和参数,但我不能完全理解语法。我想做的大致如下: private void InvokeHelper(Delegate method, params object[] args) { bool retry = false; do { try { method.DynamicInvoke(args); retry = false; } catch (MyExcept

我有一个类,其中包含一些常见的错误处理代码,我想传入要调用的方法和参数,但我不能完全理解语法。我想做的大致如下:

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

首先,你的签名是

private void InvokeHelper(Delegate method, params object[] args)
但是您犯了一个错误,即必须将arg分组到一个数组中才能调用此方法:

InvokeHelper(foo.MethodA, new object[] { a, b, c});
parms
关键字告诉编译器为您执行此操作;您可以这样调用此方法:

InvokeHelper(foo.MethodA, a, b, c);
其次,如果您的目标是3.0或更高版本,请不要使用委派,而是使用操作:

private void InvokeHelper(Action method)
    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"));
    }
这样说吧:

InvokeHelper(()=> MyMethodToInvoke(a, b, c));
这是一个更好的方法



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

这里有一个重写,下面是威尔关于使用操作的建议:

private void InvokeHelper(Action method)
    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"));
    }

“没有从方法组到委托的隐式转换”。答对 了方法具有显式声明的参数列表。通常,编译器通过检查参数的类型来帮助您确定要使用methodgroup中的哪个重载。在这里,编译器不能这样做。我将其更改为不显式构造对象数组。我不知道为什么我认为我需要这样做——我想是大脑放屁。我花了很长时间才改掉这个习惯。