我有一个可以有很多参数的程序(我们有超过+30个不同的选项)。
实施例:
myProgram.exe -t alpha 1 -prod 1 2 -sleep 200
这是3个命令(最后来自命令模式对象),每个命令都包含一些参数。在代码中我们解析所有命令(以 - 开头)并获取参数的字符串列表(拆分所有空格)。所以实际上,我们有:string - >每个命令的String参数集合。
目前,我们使用字符串比较,我们可以完成所有工作(实例具体命令并返回ICommand接口)。问题是我们每次都需要做很多IF以获得良好的命令。
您是否有一些模式可用于从EXE中提取所有参数而不使用大量IF?
代码在C#中,但我认为逻辑也可以是任何其他语言......
答案 0 :(得分:6)
(好吧,因为这是用Python标记的):
我们使用Python的optparse模块来实现此目的。它有比许多ifs更友好的API。
答案 1 :(得分:5)
创建一个哈希表,该表存储用于处理每个参数的函数指针(在C#中为委托),使用参数文本进行键控。然后,您只需在循环中浏览命令行,并根据哈希表查找的内容调用委托。
答案 2 :(得分:5)
C#的有用选项库:NDesk.Options
答案 3 :(得分:4)
getopt函数在C编程中非常常见。它可以为您解析参数。以下是C#的问题(和答案):GetOpt library for C#。
特别是lappies实现看起来像是具有属性等的现代C#。
答案 4 :(得分:1)
使用这样的命令行我会有点不舒服。我要说的第一件事是“第一个'1'是什么意思,为什么它与第二个'1'不同?”
每当我编写一个接受参数的命令行实用程序时,我认为用户学习所有选项是多么容易。在这种情况下,它看起来像是一项艰巨的任务,恕我直言。
也许重构用户如何传递参数将是一个好主意。有很多软件采用键/值类型参数的原因(例如myclient.exe -server = myServerName -config = debug)它需要大量的用户负载,并且一旦它命中代码就简化了参数解析。
答案 5 :(得分:1)
只是为了好玩,您可以围绕整个事物创建一个包装器,并在代码中使用强名称。 更多的工作?是。但更有趣的是,一旦你向包装器添加了一个新命令,你就可以忘掉它了;)
public class Form1
{
private void main()
{
MyCommandHandler CommandLineHandler = new MyCommandHandler();
CommandLineHandler.SetInput = "-t alpha 1 -prod 1 2 -sleep 200";
//now we can use strong name to work with the variables:
//CommandLineHandler.prod.ProdID
//CommandLineHandler.prod.ProdInstanceID
//CommandLineHandler.Alpha.AlhaValue()
//CommandLineHandler.Sleep.Miliseconds()
if (CommandLineHandler.Alpha.AlhaValue > 255) {
throw new Exception("Apha value out of bounds!");
}
}
}
public class MyCommandHandler
{
private string[] values;
public string SetInput {
set { values = Strings.Split(value, "-"); }
}
//Handle Prod command
public struct prodstructure
{
public string ProdID;
public string ProdInstanceID;
}
public prodstructure prod {
get {
prodstructure ret = new prodstructure();
ret.ProdID = GetArgsForCommand("prod", 0);
ret.ProdInstanceID = GetArgsForCommand("prod", 1);
return ret;
}
}
//Handle Apha command
public struct Aphastructure
{
public int AlhaValue;
}
public Aphastructure Alpha {
get {
Aphastructure ret = new Aphastructure();
ret.AlhaValue = Convert.ToInt32(GetArgsForCommand("alpha", 0));
return ret;
}
}
//Handle Sleep command
public struct SleepStructure
{
public int Miliseconds;
}
public SleepStructure Sleep {
get {
SleepStructure ret = new SleepStructure();
ret.Miliseconds = Convert.ToInt32(GetArgsForCommand("sleep", 0));
return ret;
}
}
private string GetArgsForCommand(string key, int item)
{
foreach (string c in values) {
foreach (string cc in Strings.Split(c.Trim, " ")) {
if (cc.ToLower == key.ToLower) {
try {
return Strings.Split(c.Trim, " ")(item + 1);
}
catch (Exception ex) {
return "";
}
}
}
}
return "";
}
}
答案 6 :(得分:1)
Java的答案,就像往常一样,是有人击败了你并发布了一个优秀的开源库来实现这一目标。看看Apache CLI。
答案 7 :(得分:0)
我不认为这太过分了......
private void Main()
{
string c = "-t alpha 1 -prod 1 2 -sleep 200";
foreach (string incommand in Strings.Split(c, "-")) {
HandleCommand(Strings.Split(incommand.Trim, " "));
}
}
public void HandleCommand(string[] c)
{
switch (c(0).ToLower) {
case "t":
Interaction.MsgBox("Command:" + c(0) + " params: " + c.Length - 1);
break;
case "prod":
Interaction.MsgBox("Command:" + c(0) + " params: " + c.Length - 1);
break;
case "sleep":
Interaction.MsgBox("Command:" + c(0) + " params: " + c.Length - 1);
break;
}
}
当然,不要在那些switch语句中做同样的事情,而是调用适当的函数或代码。
答案 8 :(得分:0)
通常,您可以使用Dictionary替换大型if / else或switch / case结构。 if-criteria是密钥,执行代码是值。
例如,您可以在解析命令行之前填写Dictionary<string, ICommand>
(或Dictionary<string, Type>
)。
当您遍历传入的命令行选项时,只需在字典中查找它们并“调用”作为要执行的匹配命令(对象)的值(或者如果您使用Activate.CreateInstance(/*dictionary-value*/)
存储类型而不是特定的对象实例。)
在C#3.0中,您还可以使用类似Dictionary<string, System.Linq.Expressions.Expression<T>>
的内容,尽管这可以让您非常接近实际的if语句 - 这可能是您想拥有或不拥有的内容。 YMMV。
有些库只提供了对命令行参数的解析(就像传统的getopt()等),或者可以提供整个包,包括在存在特定命令行参数时调用操作。