将可能有参数或没有参数的函数存储到变量中。 Action<T> 具有未知数量和类型的变量
Storing a function that may have parameter or not, to variable. Action<T> with unknown numbers and types of variables
我正在为控制台应用程序开发命令解析器 class,但我被困在将命令函数存储到变量中。我想将一个可能有参数或没有参数的函数存储到 Command 对象中的 commandFunc 变量。
这些代码适用于不带参数的函数。如何获得对此的参数支持?例如:像 output(string msg){ .. }
这样的函数
class Program
{
static void Main(string[] args)
{
CommandParser.AddCommand(new Command() { commandText = "time", commandFunc = new Action(time) });
CommandParser.Loop();
}
private static void time()
{
Console.WriteLine(DateTime.Now.ToLongTimeString());
}
}
在 CommandParser.Loop 中,它在 List< Command > 中搜索输入的命令,然后从中运行 Execute 方法。
public class Command
{
public string commandText { get; set; }
public Action commandFunc { get; set; }
public void Execute()
{
this.commandFunc();
}
}
例如执行方法可以是这样的:
public void Execute(Parameters params)
{
this.commandFunc(params);
}
PS: CommandParser.Loop()
public static void Loop()
{
while(true)
{
Console.Write(prefix);
string[] input = Console.ReadLine().Split(' ');
Command cmdInput = commands.Find(x => x.commandText.Contains(input[0]));
if(cmdInput != new Command())
{
cmdInput.Execute();
}
else
{
Console.WriteLine(prefix + "Command not found!");
}
}
}
嗯,您基本上需要做的是扩展对象层次结构。
在C#中,泛型不允许Something<void>
,所以你需要做的是:
public interface ICommand
{
void Execute();
}
这是添加了接口的当前实现
public class Command : ICommand
{
public string commandText { get; set; }
public Action commandFunc { get; set; }
public void Execute()
{
this.commandFunc();
}
}
并且是带参数的委托的通用实现
public class Command<T> : ICommand
{
public string commandText { get; set; }
public Action<T> commandFunc { get; set; }
public T commandParam { get; set; }
public void Execute()
{
this.commandFunc(commandParam);
}
}
如果您需要实现更多参数,您可以复制原始参数或使用 Tuple
class 作为通用参数(例如 Tuple<string, int>
)。
正如 Jon Skeet 在评论中提到的:
另一件事是您可能需要解析这些通用命令中的参数(由 commandParam
表示)。您应该使用参数(例如委托)初始化这些命令以解析参数。在命令之外执行此操作会一团糟,并破坏整个 genericity/interface 想法。但它可能适用于较小的规模。
我正在为控制台应用程序开发命令解析器 class,但我被困在将命令函数存储到变量中。我想将一个可能有参数或没有参数的函数存储到 Command 对象中的 commandFunc 变量。
这些代码适用于不带参数的函数。如何获得对此的参数支持?例如:像 output(string msg){ .. }
这样的函数class Program
{
static void Main(string[] args)
{
CommandParser.AddCommand(new Command() { commandText = "time", commandFunc = new Action(time) });
CommandParser.Loop();
}
private static void time()
{
Console.WriteLine(DateTime.Now.ToLongTimeString());
}
}
在 CommandParser.Loop 中,它在 List< Command > 中搜索输入的命令,然后从中运行 Execute 方法。
public class Command
{
public string commandText { get; set; }
public Action commandFunc { get; set; }
public void Execute()
{
this.commandFunc();
}
}
例如执行方法可以是这样的:
public void Execute(Parameters params)
{
this.commandFunc(params);
}
PS: CommandParser.Loop()
public static void Loop()
{
while(true)
{
Console.Write(prefix);
string[] input = Console.ReadLine().Split(' ');
Command cmdInput = commands.Find(x => x.commandText.Contains(input[0]));
if(cmdInput != new Command())
{
cmdInput.Execute();
}
else
{
Console.WriteLine(prefix + "Command not found!");
}
}
}
嗯,您基本上需要做的是扩展对象层次结构。
在C#中,泛型不允许Something<void>
,所以你需要做的是:
public interface ICommand
{
void Execute();
}
这是添加了接口的当前实现
public class Command : ICommand
{
public string commandText { get; set; }
public Action commandFunc { get; set; }
public void Execute()
{
this.commandFunc();
}
}
并且是带参数的委托的通用实现
public class Command<T> : ICommand
{
public string commandText { get; set; }
public Action<T> commandFunc { get; set; }
public T commandParam { get; set; }
public void Execute()
{
this.commandFunc(commandParam);
}
}
如果您需要实现更多参数,您可以复制原始参数或使用 Tuple
class 作为通用参数(例如 Tuple<string, int>
)。
正如 Jon Skeet 在评论中提到的:
另一件事是您可能需要解析这些通用命令中的参数(由 commandParam
表示)。您应该使用参数(例如委托)初始化这些命令以解析参数。在命令之外执行此操作会一团糟,并破坏整个 genericity/interface 想法。但它可能适用于较小的规模。