/// <summary> /// Adds a command line argument with values that should be parsable into <typeparamref name="T" />. /// </summary> /// <param name="app"></param> /// <param name="name"></param> /// <param name="description"></param> /// <param name="multipleValues"></param> /// <returns></returns> public static CommandArgument <T> Argument <T>(this CommandLineApplication app, string name, string description, bool multipleValues = false) => app.Argument <T>(name, description, _ => { }, multipleValues);
private static void _ConfigureInvoker(CommandLineApplication command, Type type, MethodInfo methodInfo) { var helpOpt = command.HelpOption(); var parameters = methodInfo.GetParameters(); foreach (var param in parameters) { if (param.GetCustomAttribute <ConventionOptionAttribute>() != null) { _RegisterOption(command, param.ParameterType, _PascalToKebab(param.Name), param.GetCustomAttribute <ConventionDescriptionAttribute>()?.Text ?? "", param.GetCustomAttribute <ConventionIsRequiredAttribute>() != null); } else if (_IsExpectingSingleValue(param.ParameterType) || _IsExpectingMultiValue(param.ParameterType)) { var desc = param.GetCustomAttribute <ConventionDescriptionAttribute>(); var description = desc?.Text ?? ""; command.Argument(param.Name, description, _IsExpectingMultiValue(param.ParameterType)); } } command.OnExecute(() => { if (helpOpt.HasValue()) { return(0); } CancellationTokenSource cts = null; var obj = Activator.CreateInstance(type); var alloptions = command.GetOptions(); foreach (var prop in type.GetProperties()) { var option = alloptions.FirstOrDefault(opt => opt.LongName == _PascalToKebab(prop.Name)); if (option != null) { prop.SetValue(obj, _ExtractValueFromOption(prop.PropertyType, option)); } } if (type.GetMethod("Initialize") != null) { type.GetMethod("Initialize").Invoke(obj, null); } var allArgs = command.Arguments; var handlerParams = new List <object>(); foreach (var param in methodInfo.GetParameters()) { var arg = allArgs.FirstOrDefault(a => a.Name == param.Name); var option = alloptions.FirstOrDefault(opt => opt.LongName == _PascalToKebab(param.Name)); object valueToAdd = null; if (arg != null) { if (arg.MultipleValues) { valueToAdd = _ParseMultiValue(param.ParameterType, arg.Values); } else if (param.HasDefaultValue && arg.Value == null) { valueToAdd = param.DefaultValue; } else { valueToAdd = _ParseSingleValue(param.ParameterType, arg.Value); } } else if (option != null) { if (param.HasDefaultValue && option.HasValue() == false) { valueToAdd = param.DefaultValue; } else { valueToAdd = _ExtractValueFromOption(param.ParameterType, option); } } else if (param.ParameterType == typeof(CancellationToken)) { if (cts == null) { cts = new CancellationTokenSource(); } valueToAdd = cts.Token; } else { if (type.GetMethod("ResolveType") != null) { valueToAdd = type.GetMethod("ResolveType").Invoke(obj, new[] { param.ParameterType }); } else { throw new Exception("Cannot resolve parameter type"); } } if (param.GetCustomAttribute <ConventionIsRequiredAttribute>() != null && valueToAdd == null) { throw new Exception($"{param.Name} is required"); } handlerParams.Add(valueToAdd); } var res = methodInfo.Invoke(obj, handlerParams.ToArray()); if (res.GetType() == typeof(Task <int>)) { var task = (Task <int>)res; System.Console.CancelKeyPress += (sender, e) => { cts?.Cancel(); Task.WaitAll(new[] { task }, 10000); }; AppDomain.CurrentDomain.ProcessExit += (sender, e) => { cts?.Cancel(); Task.WaitAll(new[] { task }, 10000); }; Task.WaitAll(task); return(task.Result); } else { return((int)res); } }); }