我试图用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,或者应该使用完全不同的方法?
答案 0 :(得分:3)
除了编译为Expression
之外,lambda都会编译为System.Delegate
的实例。但这是一个非常模糊的类型,您必须使用反射来发现任何东西。
通过声明一组重载来接受Action
,Action<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#的姊妹功能语言,因此可以更轻松地集成到您的项目中。函数语言(据我了解)比起操作数的本质,它更关心的是您所编写的内容的纯功能性,尽管我不确定它是否与参数数量无关。当然值得研究。