【问题标题】:Pass a method with N params as parameter in C#在 C# 中传递具有 N 个参数的方法作为参数
【发布时间】:2011-03-04 18:50:38
【问题描述】:

我有几种方法都返回具有不同签名(参数)和不同名称的 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);
    }

【问题讨论】:

  • 与代表一起做这件事不是最简单的吗?每个不同的签名都需要一个结构,您可以将这些参数放入其中。该结构公开了一个方法,Execute,然后调用传递适当参数的真实方法。
  • 可能我没看懂你的问题,但是在调用TestN("Test", 1)时,t3的值应该是多少? null?调用是否应该失败?
  • 您的目标仅仅是摆脱显式委托类型声明吗?
  • 不清楚(至少对我而言)您如何处理不同的签名。似乎 TestN 会失败,因为 t3 不是可选的。您在什么时候知道参数的值是多少?

标签: c# methods parameters delegates action


【解决方案1】:

这并不能直接回答您的问题,但这是我解决类似问题的方法:

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

code generator

同样,您可能希望有一种方法可以使用其他委托类型(例如Action&lt;string, int&gt;)。我的方法和你的不同之处在于我的方法不是后期绑定的,但你似乎并没有使用后期绑定,所以早期绑定给你一些编译时类型安全。

我不确定您是否可以按照我认为您的要求进行操作。你用一些object[] 调用method.DynamicInvoke,但是你是如何获得这些参数的值的?


为了在有人问之前回答问题,我创建了Lambda.Pin 函数,因为我厌倦了犯这个错误:

Action<int> foo;
foreach (int i in someList)
    AddAction(() => foo(i));

【讨论】:

  • 这几乎就是我一直在做的事情。这是一种皇家的痛苦,但我没有看到任何其他方式。
  • 我添加了一个指向我的简单代码生成器的链接。随意使用它并以任何你想要的方式改变它,因为它可能无论如何都是粗制滥造的。
【解决方案2】:
public void InvokeMyMethod(Delegate method) {
    Method.DynamicInvoke(new object[] {"Test", 1});
}

但是你需要像这样调用它

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

【讨论】:

  • 假设我的方法有 6 个参数,我必须为该方法创建一个新委托,这就是为什么我需要透明
  • 如果您在将方法组转换为委托时不接受强制转换,那么您就不走运了。对不起。
猜你喜欢
  • 2012-09-22
  • 2023-03-13
  • 1970-01-01
  • 2018-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
相关资源
最近更新 更多