在C#中传递带有N个参数作为参数的方法 [英] Pass a method with N params as parameter in C#

查看:87
本文介绍了在C#中传递带有N个参数作为参数的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,

我有几种方法都返回带有不同签名(参数)和不同名称的void.我需要将这些方法作为参数传递给泛型方法,然后再将其调用.另外还需要尽可能透明.

遵循我到目前为止的内容:

Hello,

I have several methods all returning void with different signature (parameters) and different names. I need to pass those methods as a parameter in a generic method that will invoke it latter. Also that need to be as transparent as possible.

Following what I got so far:

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


那就是我所需要的:


That is what I need:

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



谢谢



Thank You

推荐答案

据我所知(我也遇到了相同的问题并对其进行了研究),可悲的是,这无法完成.
我能管理的最接近的东西是这样的:
As far as I know (and I was confronted with the same problem and studied it), sadly, this cannot be done.
The closest I could manage was something like this:
private void button1_Click(object sender, EventArgs e)
{
    InvokeMyMethod(Test, "string", 1);
    InvokeMyMethod(TestN, "other string", 3, Color.Red);
}

public delegate void MyMethodDelegate(params object[] args);

public void InvokeMyMethod(MyMethodDelegate method, params object[] args)
{
    method.DynamicInvoke(args);
}

public void Test(params object[] args)
{
    if (args.Length < 2) return;
    MessageBox.Show(string.Format("{0}{1}", args[0], args[1]));
}

public void TestN(params object[] args)
{
    // or, whatewer
    if (args.Length < 3) return;
    MessageBox.Show(string.Format("{0}{1}{2}", args[0], args[1], args[2]));
}


要让您传递方法组(一种调用由普通方法名称定义的委托的简便方法),编译器必须知道所有委托参数的确切类型.您最接近所需语法的仍然会要求您显式列出参数类型.您还需要定义N个几乎相同的泛型方法,其中N是目标函数采用的最大参数数量.
To let you pass a method group (a fancy way to call a delegate defined by a plain method name) the compiler must know the exact types of all delegate''s parameters. The closest you could get to the syntax you want would still require you to list parameter types explicitly. You would also need to define N nearly identical generic methods, where N is the max number of parameters your target functions take.
public static void Main() {
    Invoke<long>(Test);
    Invoke<string,int>(Test);
    Invoke<string,int,object>(Test);
}
private static void Invoke<T1>(Action<T1> a) {
    InvokeMyMethod(a);
}
private static void Invoke<T1,T2>(Action<T1,T2> a) {
    InvokeMyMethod(a);
}
private static void Invoke<T1,T2,T3>(Action<T1,T2,T3> a) {
    InvokeMyMethod(a);
}
private static void InvokeMyMethod(Delegate method) {
    var args = new object[X]; // do your magic here
    method.DynamicInvoke(args);
}
public static void Test(long t) {
}
public static void Test(string t1, int t2) {
}
public static void Test(string t1, int t2, object t3) {
}


如果您使用预先定义的签名的固定数量的不同代表,这将非常简单.每个委托类型将具有固定数量的参数(您也可以使用params语法来模拟无限数量的相同类型的参数,但这只是一个语法上的糖果).当然,它将在参数类中包括通常的多态性.您还可以创建和使用通用委托,而不仅仅是System.ActionSystem.Func涵盖的委托.

在这种情况下,用法不需要​​任何类型转换,因此不会引起bug和混乱.如果您想公开更多动态"间接功能,那将是不值得的,您应该重新考虑您的方法.

考虑一下:

It''s quite simple if you use fixed number of different delegates with the signatures defined in advance. Each delegate type will have fixed number of parameters (you can also use params syntax to mimic unlimited number of parameters of the same type, but this is only a syntactic candy). Of course, it will include the usual polymorphism in parameter classes. You can also create and use generic delegates, not only those covered by System.Action or System.Func.

In this case, the usage will not require any type cast, so it won''t be an invitation for bugs and mess-ups. If you want to expose more "dynamic" indirection feature, I would say, it wouldn''t worth the effort and you should reconsider you approach.

Consider this:

delegate void MySimpleDelegate(int a, string b, DelegateUser user);
delegate void MySimpleDelegateWithParamsArray(DelegateUser user, int a, params string[] b);
delegate int MyDelegateWithByRef(int a, ref string b);
delegate int MyDelegateWithOut(int a, string b, out string c);
delegate void MyGenericDelegate<FIRST, SECOND>( //same as System.Action
    DelegateUser user,
    FIRST first,
    SECOND second); 

class DelegateUser {
    internal void Call(MySimpleDelegate[] methods, int a, string b) {
        foreach (MySimpleDelegate methodInstance in methods)
            methodInstance(a, b, this);
    } //Call
    internal void Call(MySimpleDelegateWithParamsArray[] methods, int a, params string[] b) {
        foreach (MySimpleDelegateWithParamsArray methodInstance in methods)
            methodInstance(this, a, b);
    } //Call
    internal void Call(MyDelegateWithByRef method, int a, ref string b) {
        method(a, ref b);
    } //Call
    internal void Call(MyDelegateWithOut method, int a, string b, out string c) {
        method(a, b, out c);
    } //Call
    internal void Call<FIRST, SECOND>(
        MyGenericDelegate<FIRST, SECOND>[] methods,
        DelegateUser user, FIRST first, SECOND second) {
            foreach (MyGenericDelegate<FIRST, SECOND> methodInstance in methods)
                methodInstance(this, first, second);
    } //Call
    internal string Value { get; set; }
    //...
} //class DelegateUser

//usage example:
class Test {
    void TestCalls() {
        DelegateUser user = new DelegateUser();
        user.Call<int, double>(new MyGenericDelegate<int, double>[] {
            delegate(DelegateUser userRef, int iValue, double dValue) {
                user.Value =
                    string.Format("Firt: {0}: {1}, {2}",
                    user.Value, iValue, dValue);
            },
            delegate(DelegateUser userRef, int iValue, double dValue) {
                user.Value =
                    string.Format("Second: {0}: {1}, {2}",
                    user.Value, iValue, dValue);
            }
        }, user, 3, 3d);
    }
} //class Test




该类没有意义,仅用于演示语法.对于傻笑,我还添加了一个委托数组,但是通常不需要,因为每个委托实例都是多播的,所以另一种(更好的)方法是将多个方法添加到同一个委托实例中.
仅当委托代码和您调用的类代码一起做某事时,此技术才有用.例如,委托可以对作为参数传递的类的实例进行操作:您的类计算参数,委托实例为其添加自定义处理.

很常见的情况是正在收集中.例如,一个调用类提供了一个迭代器来处理某些对象集合,并且委托实例使用foreach循环为每个集合成员执行一些自定义处理.有关此类技术的说明,请在此处查看我的旧答案:




This class makes no sense, it''s only to demonstrate the syntax. For giggles, I also added array of delegates, but it is not usually needed, because each delegate instance is mult-cast, so the other (better) way of doing is adding multiple method to the same delegate instance.

This technique is only useful if a delegate code and you calling class code are doing something together. For example, a delegate could operate on instance of the class passed as a parameter: you class calculates a parameter, you delegate instance add custom processing to it.

Very usual case is working on collection. For example, a calling class provides an iterator to work with some collection of objects, and the delegate instance performs some custom processing for each of the collection members, using foreach loop. For explanation of such techniques, please see my old Answer here: What are the advantages of delegates in C#.NET?[^].

—SA


这篇关于在C#中传递带有N个参数作为参数的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆