繁体   English   中英

如何使用NDesk.Options强制执行必需的命令行选项?

[英]How to enforce required command-line options with NDesk.Options?

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

我在文档中看到:

具有必需值(在选项名称后附加'=')或可选值(在选项名称后附加':')的选项。

但是,当我在选项名称的末尾添加=时,行为没有区别。 理想情况下,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);
    }
}

问题在于文档不像显然需要的那样清晰。 :-(

具体来说,按照:

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=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");

可以稍微扩展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和私有bool optionSet。

第四,在创建目标值时将其传递给Option。 订阅PropertyChanged事件。 如果发件人不为null,则在其中将“ optionSet”设置为true。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM