很多不同类的命令行参数

时间:2014-03-12 11:06:30

标签: c# parsing design-patterns command-line

我们使用特定的软件来执行我的控制台应用程序,其中包含大量参数(现在它的25(!)可能会越来越多)。当然,不同的类需要不同的论点。我用NDesk.Options解析它。但是,我一次又一次地为所有班级做过。

class A {
    A (IEnumerable<String> args){
        new OptionSet {
            { "arg1=", value => foo1 = value },
                { "arg2=", value => foo2 = value },
            ...
        }.Parse(args);
    }
}
class B {
    B (IEnumerable<String> args){
        new OptionSet {
            { "arg10=", value => foo10 = value },
                { "arg11=", value => foo11 = value },
            ...
        }.Parse(args);
    }
}

如何为好的设计做到这一点?解析静态类中的所有参数并使用它或其他东西吗?

2 个答案:

答案 0 :(得分:6)

由于您要求设计模式,这听起来像是Interpreter pattern的工作。

否则,根据我的经验,命令行参数&#39;解析&#39; 模式匹配是一个很好的例子,不幸的是,C#没有,但F#确实如此。在ZeroToNine中,当前的参数匹配如下所示:

let Parse argv =
    match argv |> Seq.toList with
    | ["-l"] -> ListVersions
    | ["-a"; IsProperVersionString version] -> Assign version
    | ["-i"; "major"] -> Increment Rank.Major
    | ["-i"; "minor"] -> Increment Rank.Minor
    | ["-i"; "build"] -> Increment Rank.Build
    | ["-i"; "patch"] -> Increment Rank.Build
    | ["-i"; "revision"] -> Increment Rank.Revision
    | ["-a"; "major"; IntegerGreaterThanOrEqualToZero rankValue] -> AssignRank(Rank.Major, rankValue)
    | ["-a"; "minor"; IntegerGreaterThanOrEqualToZero rankValue] -> AssignRank(Rank.Minor, rankValue)
    | ["-a"; "build"; IntegerGreaterThanOrEqualToZero rankValue] -> AssignRank(Rank.Build, rankValue)
    | ["-a"; "patch"; IntegerGreaterThanOrEqualToZero rankValue] -> AssignRank(Rank.Build, rankValue)
    | ["-a"; "revision"; IntegerGreaterThanOrEqualToZero rankValue] -> AssignRank(Rank.Revision, rankValue)
    | ["-?"] -> ShowHelp
    | ["-h"] -> ShowHelp
    | [] -> ShowHelp
    | x -> Unknown(x)
    |> Seq.singleton

当然,我们没有25个不同的论点,但上面的例子仍然可以让你很好地理解处理各种案件是多么容易。

即使您拥有C#代码库,也可以在F#中编写解析器库。

略有不同的说明:如果你的控制台应用程序需要25个不同的参数,将它分成几个较小的控制台应用程序是否有意义?这听起来好像做了很多。

答案 1 :(得分:0)

Builder pattern可用于使用命令行参数配置解析器和/或类。这避免了具有大量参数的构造函数,其中一些可能是可选的。它允许轻松添加新参数。

Apache有一个很好的Builder与命令行解析一起使用的例子。

另一方面,Builder很冒险。它有时用于避免具有太多参数的构造函数的反模式。反模式的原因是因为你可能暴露了太多的类秘密(实现细节),或同样糟糕,这个类有太多的责任。

正如我在你对你的问题的评论中提到的那样,争论很多并且一直在变化这一事实可能是一个糟糕的高级别设计的标志。没有更多细节,很难说。