有没有一种方法可以声明一个将lambda作为参数的方法?

时间:2019-08-25 20:15:29

标签: c# .net reflection

我试图用C#编写一个可以接受任何类型的lambda的方法,但是我不知道该怎么做。

我正在开发一个将处理文本命令的类。我想以这样一种方式实现它,即可以从处理特定命令的lambda表达式中自动确定参数。

以下是我想要获取的API的示例:

commandProcessor.AddCommand("setpos", (int x, int y)=>{
    //do stuff
});
commandProcessor.AddCommand("changename",(string newName)=>{
    //do completely different stuff
});

我的命令处理器将如下所示:

Dictionary<string, MagicType> mCommands;

public void AddCommand(string commandName, MagicType commandHandler){
    mCommands[commandName] = commandHandler;
}

是否可以使用MagicType,或者应该使用完全不同的方法?

2 个答案:

答案 0 :(得分:3)

除了编译为Expression之外,lambda都会编译为System.Delegate的实例。但这是一个非常模糊的类型,您必须使用反射来发现任何东西。

通过声明一组重载来接受ActionAction<T>Action<T1, T2>等,可能会更好。这些是BCL的内置委托类型,用于返回{{1 }}。

答案 1 :(得分:3)

如果您确实需要这种功能,则可以执行以下操作。

public delegate object GenericCommand (params object[] parameters);

然后,您需要为要存储的每个与GenericCommand定义兼容的方法提供重载。

这是一个示例。

using System;
using System.Collections.Generic;

public class Program
{
    public delegate object GenericCommand (params object[] parameters);

    public static object Function1 (params object[] parameters) => Function1 ((int)parameters[0], (int)parameters[1]);
    public static int Function1 (int i, int j) => (i + j);

    private static Dictionary<string, GenericCommand> commands;

    public static void Main()
    {
        commands = new Dictionary<string, GenericCommand> ();

        commands.Add ("Function1", Function1);

        int i = (int)commands["Function1"](1, 2);

        Console.WriteLine (i); // 3
    }   
}

说了这么多,用C#这样的语言来做这有点棘手,这是有原因的。在强类型语言中,期望的是在调用方法时,用户会想到一组特定的输入,并期望返回特定类型的输出。通常不需要像GenericCommand这样的非描述性内容,因为如果您知道该方法的名称以及该方法的正常使用位置,为什么不直接调用它呢?

如果您发现自己的程序中非常需要这种功能,那么我会考虑也许用另一种语言编写基线的这一部分。我对此的了解是有限的,但是我相信F#可以毫无困难地完成您的要求。 Javascript是另一种选择,但是F#是C#的姊妹功能语言,因此可以更轻松地集成到您的项目中。函数语言(据我了解)比起操作数的本质,它更关心的是您所编写的内容的纯功能性,尽管我不确定它是否与参数数量无关。当然值得研究。