32

GUI とコマンド ライン実行の両方を備えたツールとしてCommandLine Parser Libraryの使用を開始しました。GUI の起動は、コマンド ライン オプションを使用して行います。

したがって、プログラムがコマンド ライン モードで実行されている場合に備えて、必要なオプションが必要です。基本的に、オプション「Gui」が設定されていない場合は、オプション 1 とオプション 2 を必須にする必要があります。

MutuallyExclusiveSet 属性と Required 属性を以下のように組み合わせてみましたが、思うように動きません。「MutuallyExclusiveSet」の概念を誤解したり、単に誤用したりしましたか? それとも、ライブラリがまだサポートしていないものですか?

public class CommandLineOptions : CommandLineOptionsBase
{
    [Option(null, "gui", Required = false, HelpText = "Launch the GUI", MutuallyExclusiveSet = "Gui")]
    public bool Gui { get; set; }

    [Option(null, "opt1", HelpText = "Option 1", MutuallyExclusiveSet = "CommandLine", Required = true)]
    public string Option1 { get; set; }

    [Option(null, "opt2", HelpText = "Option 2", MutuallyExclusiveSet = "CommandLine", Required = true)]
    public string Option2 { get; set; }
}
4

1 に答える 1

52

相互に排他的なセットに属するすべてのオプションは、それらの間で相互に排他的です。次の例に従います。

class Options {
  [Option("a", null, MutuallyExclusiveSet="zero")] 
  public string OptionA { get; set; }
  [Option("b", null, MutuallyExclusiveSet="zero")] 
  public string OptionB { get; set; }
  [Option("c", null, MutuallyExclusiveSet="one")] 
  public string OptionC { get; set; }
  [Option("d", null, MutuallyExclusiveSet="one")] 
  public string OptionD { get; set; }
}

これらのルールでは、次のコマンド ラインが有効です。

$ app -a foo -c bar
$ app -a foo -d bar
$ app -b foo -c bar
$ app -b foo -d bar

これらはそうではありません:

$ app -a foo -b bar
$ app -c foo -d bar
$ app -a foo -b bar -c foo1 -d foo2

ご覧のとおり、同じセットに属するオプションを一緒に指定することはできません。また、ビルド済みのシングルトン ( CommandLineParser.Default ) はMutualliyExclusiveSet属性では機能しないことにも注意してください。自分でパーサーをドレスアップする必要があります。

if (new CommandLineParser(new CommandLineParserSettings {
                            MutuallyExclusive = true,
                            CaseSensitive = true,
                            HelpWriter = Console.Error}).ParseArguments(args, opts) {
  // consume values here
  Console.WriteLine(opts.OptionA);
}

これは、コマンド ライン パーサー ライブラリで相互に排他的なオプションが機能する方法です。とにかく、特定の問題を解決するには、通常のコンソール アプリケーションで行うように、すべてのオプションを定義することをお勧めします。次に、 Guiブール スイッチを追加します。このオプションが指定されている場合、他のオプションは無視されます。通常のコンソール アプリとして動作しない場合。

(別のこと: 後続のバージョンでは、複数のオプション タイプを管理できる「サブコマンド」と呼ばれる機能が予定されています。これは、この次の機能の適切なケースかもしれません。)

編集 2015-08-30:

1.9.x 安定版で実装された機能は常に混乱を招き、デフォルトでは無効になっており、開発者は設定インスタンスを介して有効にする必要がありました。

カーネルが完全に書き直されたバージョン 2.0.x では、この機能は常にアクティブです。簡単な例を示してみます (2.0.x はメジャー リリース アップデートであるため、パブリック API が変更されていることに注意してください)。


class Options {
  [Option(SetName = "web")]
  public string WebUrl { get; set; }
  [Option(SetName = "web")]
  public int MaxLinks { get; set; }

  [Option(SetName = "ftp")]
  public string FtpUrl { get; set; }
  [Option(SetName = "ftp")]
  public int MaxFiles { get; set; }

  [Option]
  public bool Verbose { get; set; }
}

セットからのセットは、からのftpものと互換性がありません (セットに属していないか、デフォルトのセットに属している方が良いです。ニュートラルであり、自由に混合できます)。有効:web--verbose""


$ app --weburl http://stackoverflow.com --maxlinks 99
$ app --ftpurl ftp://ftp.myoffice.files.com --maxfiles 1234
$ app --verbose --weburl http://twitter.com --maxlinks 777
$ app --ftpurl ftp://ftp.xyz.org --maxfiles 44 --verbose
$ app --verbose

有効ではありません:


$ app --weburl http://stackoverflow.com --maxlinks 99 --ftpurl ftp://ftp.xyz.org
$ app --ftpurl ftp://ftp.myoffice.files.com --maxfiles 1234 --maxlinks 777
$ app --verbose --weburl http://twitter.com --maxfiles 44
$ app --maxfiles 44 --maxlinks 99
于 2012-05-27T15:14:12.513 に答える