コード例 #1
0
 /// <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);
                }
            });
        }