commandline icon indicating copy to clipboard operation
commandline copied to clipboard

Cannot assign null as DefaultValue for collection options

Open akbyrd opened this issue 10 years ago • 0 comments

[CommandLine.Option('r', "ToggleRefreshRate", Max = 5, DefaultValue = null)]
public IEnumerable<int> ToggleRefreshRate { get; set; }

causes exception:

Unhandled Exception: System.Reflection.CustomAttributeFormatException: 'DefaultValue' property specified was not found. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.

ArgumentNullException: Value cannot be null.
Parameter name: value
   at CommandLine.OptionAttribute.set_DefaultValue(Object value)
   --- End of inner exception stack trace ---

   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvoke(Object obj, BindingFlagsinvokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
   --- End of inner exception stack trace ---

   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimePropertyInfoproperty, RuntimeType caType)
   at System.Reflection.RuntimePropertyInfo.GetCustomAttributes(Boolean inherit)

   at CommandLine.Core.ReflectionExtensions.<GetSpecifications>b__2[T](PropertyInfo pi)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Linq.Lookup`2.Create[TSource](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.GroupedEnumerable`3.GetEnumerator()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at CommandLine.Core.ReflectionExtensions.<GetSpecifications>d__f`1.MoveNext()

   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
   at CommandLine.Core.SpecificationExtensions.ThrowingValidate(IEnumerable`1 specifications, IEnumerable`1 guardsLookup)
   at CommandLine.Core.InstanceBuilder.Build[T](Func`1 factory, Func`3 tokenizer, IEnumerable`1 arguments, StringComparer nameComparer, CultureInfo parsingCulture)
   at CommandLine.Parser.<>c__DisplayClass4`1.<ParseArguments>b__2()
   at CommandLine.Parser.MakeParserResult[T](Func`1 parseFunc, ParserSettings settings)
   at CommandLine.Parser.ParseArguments[T](Func`1 factory, String[] args)
   at CommandLine.Parser.ParseArguments[T](String[] args)
   at GameSettings.Program.Main(String[] args) in d:\Dev\Github\GameSettings\Game Settings\Program.cs:line 19

This makes it impossible to tell if the user actually supplied the option or not. I only need to perform an action if the option was actually specified on the command line, but specifying the option with zero items is a valid use case and I need to handle it. Currently, it is impossible to tell the difference between myapp -ToggleRefreshRate -otherstuff and myapp -otherstuff

Tested on version 2.0.0.0

akbyrd avatar May 31 '15 18:05 akbyrd