Передать метод с N params в качестве параметра в C # - PullRequest
2 голосов
/ 04 марта 2011

У меня есть несколько методов, возвращающих void с разными сигнатурами (параметрами) и разными именами. Мне нужно передать эти методы в качестве параметра в общий метод, который вызовет его позже. Также это должно быть максимально прозрачно.

После того, что я получил до сих пор:

    private void button1_Click(object sender, EventArgs e)
    {
        Action<string,int> TestHandler = Test;
        InvokeMyMethod(TestHandler);

        Action<string, int,object > TestHandlerN = TestN;
        InvokeMyMethod(TestHandlerN);
    }        
public void InvokeMyMethod(Delegate Method)
    {
          object[] args = new object[X];            
          Method.DynamicInvoke();
    }

    public void Test(string t1, int t2)
    {
        MessageBox.Show(t1 + t2);
    }

    public void TestN(string t1, int t2, object t3)
    {
        MessageBox.Show(t1 + t2);
    }

Вот что мне нужно:

    private void button1_Click(object sender, EventArgs e)
    {
        InvokeMyMethod(Test);
        InvokeMyMethod(TestN);
    }

    public void InvokeMyMethod(XXX_Type Method)
    {
         object[] args = new object[X];
         Method.DynamicInvoke(args);
    }

    public void Test(string t1, int t2)
    {
        MessageBox.Show(t1 + t2);
    }

    public void TestN(string t1, int t2, object t3)
    {
        MessageBox.Show(t1 + t2);
    }

Ответы [ 2 ]

2 голосов
/ 04 марта 2011

Это не отвечает на ваш вопрос напрямую, но вот как я решаю подобную проблему:

public static partial class Lambda
{
    public static Action Pin<T0>
        (
            this Action<T0> action,
            T0 arg0
        )
    {
        return () => action(arg0);
    }

    public static Func<TResult> Pin<T0, TResult>
        (
            this Func<T0, TResult> func,
            T0 arg0
        )
    {
        return () => func(arg0);
    }

    public static Action Pin<T0, T1>
        (
            this Action<T0, T1> action,
            T0 arg0,
            T1 arg1
        )
    {
        return () => action(arg0, arg1);
    }

    public static Func<TResult> Pin<T0, T1, TResult>
        (
            this Func<T0, T1, TResult> func,
            T0 arg0,
            T1 arg1
        )
    {
        return () => func(arg0, arg1);
    }

    // More signatures omitted for brevity...
    // I would love it if C# supported variadic template parameters :-)
}

Идея состоит в том, что если у вас есть Action, который требует аргументов, вы можете сказать:

Action<int, string> foo;
Action a = foo.Pin(5, "bleh");

Имейте генератор кода .

Точно так же вы можете захотеть иметь способ карри к другому типу делегата (например, Action<string, int>). Разница между моим и вашим методом состоит в том, что мой метод не связан с поздним связыванием, но вы все равно не используете позднее связывание, поэтому раннее связывание дает вам некоторую безопасность при компиляции.

Я не уверен, что вы можете сделать то, что, как я думаю, вы спрашиваете. Вы вызываете method.DynamicInvoke с некоторыми object[], но как вы получили значения для этих параметров?


И чтобы ответить на вопрос, прежде чем кто-либо его спросит, я создал функции Lambda.Pin, потому что устал от этой ошибки:

Action<int> foo;
foreach (int i in someList)
    AddAction(() => foo(i));
1 голос
/ 04 марта 2011
public void InvokeMyMethod(Delegate method) {
    Method.DynamicInvoke(new object[] {"Test", 1});
}

Но вам нужно вызвать его как

InvokeMyMethod((Action<string, int>)Test);
...