C# - 使用任意数量的自定义参数进行委托 [英] C# - Delegate with any amount of custom parameters

查看:139
本文介绍了C# - 使用任意数量的自定义参数进行委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个可以存储在变量中以供以后使用的委托,该变量具有自定义量的自定义参数。我的意思是,我想用不同的返回类型和不同的参数来p it不同的方法。例如:

I want a delegate that I can store in a variable for later use that has custom amounts of custom parameters. What I mean by that, is that I want to pus it different methods with different return types and different arguments. For example:

public double Sum (double a, double b) {return a + b;}
public char GetFirst (string a) {return a[0];}
public bool canFlipTable (object[] thingsOnIt) {return thingsOnIt.Length <= 3;}

DoTheThing<double> thing1 = new DoTheThing<double>(Sum);
DoTheThing<char> thing2 = new DoTheThing<char>(GetFirst);
DoTheThing<bool> thing3 = new DoTheThing<bool>(canFlipTable);

thing1.Call(10.3, 5.6);  //15.9
thing2.Call("Hello World");  //'H'
thing3.Call(new object[] {new Lamp(), new Laptop(), new CoffeMug()});  //true

我已经找出了返回值和调用方法,但是我有一个存储方法的问题

I figured out the return value and the call method already, but I'm having a problem with storing the methods

如果我使用public DoTheThing(Action方法),则说明参数不匹配
我甚至尝试使用有params object [] p作为参数的代理,但是它不起作用。

If I use "public DoTheThing(Action method)" it says, that the arguments doesn't match I even tried with a delegate that had "params object[] p" as arguments, but it didn't work either

编辑:
我忘了告诉,方法总是有一个返回类型和至少一个参数

I forgot to tell, the method WILL always have a return type and at least 1 parameter

编辑2:
我的目标是创建一个包装类,它从非常昂贵的方法缓存输出,如果相同事情再次被调用,它返回缓存的值。
当然我可以使用一个界面来解决这个问题,但是我想这样做,我不能简单地编辑的类,我也想要这样做,所以把缓存放在同一个地方,我称之为方法也不是一个选择。

EDIT 2: My goal is creating a wrapper class, that caches outputs from very expensive methods and if the same thing gets called again, it returns the cached value. Of course I could solve this with an interface, but I want to do this with classes that I can't simply edit and I want to make this felxible too, so having the cache at the same place where I call the method is not an option either.

我的代码sofar:

public class DoTheThing <T>
{
    public delegate T Method(params object[] parameters);

    Func<T> method;
    ParameterInfo[] pInfo;

    public DoTheThing (Method method)
    {
        this.method = method;
        Type type = typeof(Method);
        MethodInfo info = type.GetMethod ("Invoke");
        if (info.ReturnType != typeof(T)) {
            throw new Exception ("Type of DoTheThing and method don't match");
        }
        pInfo = info.GetParameters ();
    }

    public T Call (params object[] parameters) {
        if (parameters.Length != pInfo.Length) {
            throw new Exception ("Wrong number of arguments, " + parameters.Length + " instead of " + pInfo.Length);
            return default(T);
        }

        for (int i = 0; i < parameters.Length; i++) {
            if (pInfo[i].ParameterType != parameters[i].GetType()) {
                throw new Exception ("Wrong parameter: " + parameters [i].GetType () + " instead of " + pInfo [i].ParameterType + " at position: " + i);
                return default(T);
            }
        }

        return (T)method.DynamicInvoke (parameters);
    }
}


推荐答案

之前试图弄清楚如何做,我真的会质疑导致我有这样一个代表的问题。我会打赌如果我更好地了解上下文,那将会有一个解决方案可以消除您的需求。

Before trying to figure how to do it, I would really question the problem that leads me to have such a kind of delegate. I would bet if I knew the context better, there would be a solution that would eliminate your requirement.

如果是这样,代理是继承自MulticastDelegate的类。事实上,当你声明一个委托时,你正在使用MulticastDelegate作为基类创建一个新的类类型。这意味着以下代码可以工作:

Having that said, delegates are classes that inherit from MulticastDelegate. In fact, when you declare a delegate, you are creating a new class type with MulticastDelegate as its base class. That means the following code works:

    public static double Sum(double a, double b)
    {
        return a + b;
    }

    public static string SayHello()
    {
        return "Hello";
    }

    static void Main(string[] args)
    {
        MulticastDelegate mydel = new Func<double, double, double>(Sum);
        var ret = mydel.DynamicInvoke(1, 2);
        System.Console.WriteLine(ret);

        mydel = new Func<string>(SayHello);
        ret = mydel.DynamicInvoke();
        System.Console.WriteLine(ret);


        mydel = new Func<string, int, string> ((s, i) => { 
            return $"Would be {s}, {i} times";
         });
        ret = mydel.DynamicInvoke("Hello", 5);
        System.Console.WriteLine(ret);
    }

由于mydel变量是基类类型(MulticastDelegate)实际上可以使用它与任何类型的委托,并用任意参数调用它。如果它们不匹配被调用的方法,它将在运行时抛出。

Because "mydel" variable is of the base class type (MulticastDelegate), we can actually use it with any kind of delegate and invoke it with arbitrary parameters. If they don't match the method being invoked, it will throw at runtime.

这篇关于C# - 使用任意数量的自定义参数进行委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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