2010-08-06 34 views
34

我只是写了一个控制台实用程序,并决定使用NDesk.Options进行命令行解析。我的问题是,我如何执行必需的命令行选项?如何使用NDesk.Options强制执行必需的命令行选项?

我在docs看出:具有所需值

选项(附加“=”与选项名称)或可选值(追加“:”在选项名称)。

但是,当我在选项名称末尾加上=时,行为没有区别。理想情况下,Parse方法会抛出异常。

有什么我需要做的吗?

这里是我的测试代码:

class Program 
{ 
    static void Main(string[] args) 
    { 
     bool show_help = false; 
     string someoption = null; 

     var p = new OptionSet() { 
      { "someoption=", "Some String Option", v => someoption = v}, 
      { "h|help", "show this message and exit", v => show_help = v != null } 
     }; 

     List<string> extra; 
     try 
     { 
      extra = p.Parse(args); 
     } 
     catch (OptionException e) 
     { 
      System.Console.Write("myconsole: "); 
      System.Console.WriteLine(e.Message); 
      System.Console.WriteLine("Try `myconsole --help' for more information."); 
      return; 
     } 

     if (show_help) 
     { 
      ShowHelp(p); 
      return; 
     } 

     System.Console.WriteLine("=================="); 
     System.Console.WriteLine(someoption); 
    } 

    static void ShowHelp(OptionSet p) 
    { 
     System.Console.WriteLine("Usage: myconsole [OPTIONS]"); 
     System.Console.WriteLine(); 
     System.Console.WriteLine("Options:"); 
     p.WriteOptionDescriptions(System.Console.Out); 
    } 
} 
+1

我有同样的问题。接缝NDesk.Options不会抛出异常。 – 2010-09-08 15:53:50

回答

39

的问题是,文件不明确的,因为它显然必须这样做。 :-(

具体来说,按照:

http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionValueType.html#F:NDesk.Options.OptionValueType.Required

选项规范并不适用于OptionSet作为一个整体中的=,而只是针对特定选项

这一点的重要性真的只有在两种情况下相关的,所以首先让我们考虑OptionSet解析器:

string a = null; 
string b = null; 
var options = new OptionSet { 
    { "a=", v => a = v }, 
    { "b=", v => b = v }, 
}; 

情况1重要的是,OptionSet.Parse()以单向,只进方式工作,并且不是查看选项值以确定它们是否应该是值。因此,可以考虑:

options.Parse(new[]{"-a", "-b"}); 

这样做的结果将是a具有价值"-b",并bnull。由于-a的处理程序需要 a值,因此始终为会得到以下值(除非该值已“编码”为原始选项,例如-a=value)。

第二个地方,这是很重要的是当值,需要选择是最后的选择,并没有存在的价值了吧:

options.Parse(new[]{"-a"}); 

这将引发OptionException,作为处理对于-a需要一个值,并且不存在任何值。

因此,如果你有自己需要(而不是需要值的选项)选项,则需要手动检查此:

string dir = null; 
new OptionSet { 
    { "o=", v => dir = v }, 
}.Parse (args); 

if (dir == null) 
    throw new InvalidOperationException ("Missing required option -o=DIR"); 
2

一个可以扩展NDesk.Options一点位来添加此功能。

首先,创建一个类SetupOption将执行INotifyPropertyChanged:

class SetupOption<T> : INotifyPropertyChanged 
{ 
    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    private T _value; 

    public T Value 
    { 
     get 
     { 
      return _value; 
     } 
     set 
     { 
      _value = value; 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(_value, new PropertyChangedEventArgs("Value")); 
      } 
     } 
    } 
} 

二,添加一个超载ActionOption这需要INotifyPropertyChanged的实例作为参数(称之为targetValue)。

三,修改Option类以添加私有的INotifyPropertyChanged targetValue和private bool optionSet。

四,创建时将targetValue传递给Option。订阅PropertyChanged事件。其中,如果发件人不为空,请将“optionSet”设置为true。

将Validate()方法添加到Option类,如果targetValue不为null且o​​ptionSet为false,则会引发异常。

最后,将一个Validate()方法添加到OptionContext中,该方法将遍历所有选项并调用其各自的Validate()方法。在Parse()方法的最后调用它。

这是修改后的代码的zip:http://www.davidair.com/misc/options.zip

相关问题