Делегат для любого типа метода — C#

Я хочу иметь класс, который будет выполнять любой внешний метод, например:

class CrazyClass
{
  //other stuff

  public AnyReturnType Execute(AnyKindOfMethod Method, object[] ParametersForMethod)
  {
    //more stuff
    return Method(ParametersForMethod) //or something like that
  }
}

Это возможно? Есть ли делегат, который принимает любую сигнатуру метода?


person Daniel Möller    schedule 02.04.2013    source источник
comment
Как узнать, какие параметры ему передать? Что произойдет, если вы ошибетесь с количеством и типом параметров?   -  person Servy    schedule 02.04.2013


Ответы (3)


Вы можете сделать это по-другому с помощью Func<T> и замыканий:

public T Execute<T>(Func<T> method)
{
   // stuff
   return method();
}

Затем вызывающая сторона может использовать замыкания для ее реализации:

var result = yourClassInstance.Execute(() => SomeMethod(arg1, arg2, arg3));

Преимущество здесь в том, что вы позволяете компилятору выполнять всю тяжелую работу за вас, а вызовы методов и возвращаемое значение являются безопасными по типам, обеспечивают интеллигентность и т. д.

person Reed Copsey    schedule 02.04.2013
comment
Можем ли мы сделать это в конструкторе CrazyClass? Если да, то как? - person toddmo; 06.12.2013
comment
@toddmo - вам нужно сделать CrazyClass универсальным, если вы хотите это сделать. - person Reed Copsey; 06.12.2013
comment
Это требует, чтобы аргументы метода были известны и привязаны к лямбде при вызове Execute(...). Его нельзя использовать для запуска любого метода с любыми параметрами. - person Peteter; 19.09.2019

Я думаю, вам лучше использовать отражения в этом случае, так как вы получите именно то, что просили в вопросе - любой метод (статический или экземпляр), любые параметры:

public object Execute(MethodInfo mi, object instance = null, object[] parameters = null)
{
    return mi.Invoke(instance, parameters);
}

Это System.Reflection.MethodInfo класс.

person Nenad    schedule 02.04.2013

Это зависит от того, почему вы хотите это сделать в первую очередь ... Я бы сделал это, используя универсальный Func, чтобы CrazyClass все еще не знал о параметрах.

class CrazyClass
{
    //other stuff

    public T Execute<T>(Func<T> Method)
    {
        //more stuff
        return Method();//or something like that
    }


}

class Program
{
    public static int Foo(int a, int b)
    {
        return a + b;
    }
    static void Main(string[] args)
    {
        CrazyClass cc = new CrazyClass();
        int someargs1 = 20;
        int someargs2 = 10;
        Func<int> method = new Func<int>(()=>Foo(someargs1,someargs2));
        cc.Execute(method);
        //which begs the question why the user wouldn't just do this:
        Foo(someargs1, someargs2);
    }
}
person IdeaHat    schedule 02.04.2013