代码之家  ›  专栏  ›  技术社区  ›  Eddie Deyo

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

c#
  •  2
  • Eddie Deyo  · 技术社区  · 17 年前

    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 回复  |  直到 17 年前
        1
  •  4
  •   user1228 user1228    17 年前

    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)
    

    这样说吧:

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

    这是一个更好的方法。


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

        2
  •  2
  •   Amy B    17 年前

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