Beispiel #1
0
        /// <summary>
        /// Run command on <paramref name="type"/> and return exit code of executed command.
        /// </summary>
        /// <param name="type">Type to look for commands on.</param>
        /// <param name="arguments">List of command line arguments. First positional parameter is treated as command's name.</param>
        /// <param name="defaultCommandName">Default command name if no command name is specified as first parameter of <paramref name="arguments"/>.</param>
        /// <returns>Exit code of command-or-<see cref="DotNetExceptionExitCode"/> if exception happened-or-<see cref="BindFailureExitCode"/> if command not found and description is shown.</returns>
        public static int Run(Type type, CommandLineArguments arguments, string defaultCommandName = null)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (arguments == null)
            {
                throw new ArgumentNullException("arguments");
            }

            try
            {
                var bindResult = BindMethod(type, defaultCommandName, arguments);

                if (bindResult.IsSuccess)
                {
                    return((int)bindResult.Method.Invoke(null, bindResult.Arguments));
                }
                else
                {
                    var bestMatchMethod = (from bindingKeyValue in bindResult.FailedMethodBindings
                                           let parameters = bindingKeyValue.Value
                                                            let method = bindingKeyValue.Key
                                                                         orderby parameters.Count(parameter => parameter.IsSuccess) descending
                                                                         select method).FirstOrDefault();

                    var error = default(CommandLineException);
                    if (bestMatchMethod == null)
                    {
                        error = CommandLineException.CommandNotFound(bindResult.MethodName);
                    }
                    else
                    {
                        error = CommandLineException.InvalidCommandParameters(bestMatchMethod, bindResult.FailedMethodBindings[bestMatchMethod]);
                    }

                    if (DescribeOnBindFailure)
                    {
                        if (bindResult.MethodName == UnknownMethodName)
                        {
                            Console.WriteLine(" Error:");
                            Console.WriteLine("  No command is specified.");
                            Console.WriteLine();

                            if (WriteWholeErrorMessageOnBindFailure)
                            {
                                Console.Error.WriteLine(error);
                                Console.Error.WriteLine();
                            }

                            Describe(type);
                        }
                        else if (bestMatchMethod != null)
                        {
                            Console.WriteLine(" Error:");
                            Console.WriteLine(string.Format("  Invalid parameters specified for '{0}' command.", bindResult.MethodName));
                            Console.WriteLine();

                            if (WriteWholeErrorMessageOnBindFailure)
                            {
                                Console.Error.WriteLine(error);
                                Console.Error.WriteLine();
                            }

                            Describe(type, bindResult.MethodName);
                        }
                        else
                        {
                            Console.WriteLine(" Error:");
                            Console.WriteLine(error.Message);
                            Console.WriteLine();
                        }
                    }
                    else
                    {
                        throw error;
                    }
                }

                return(BindFailureExitCode);
            }
            catch (Exception exception)
            {
                var handler = UnhandledException ?? DefaultUnhandledExceptionHandler;
                handler(null, new ExceptionEventArgs(exception));

                return(DotNetExceptionExitCode);
            }
        }
        internal static CommandLineException InvalidCommandParameters(MethodInfo commandMethod, ParameterBindResult[] parameterBindResults)
        {
            if (commandMethod == null)
            {
                throw new ArgumentNullException("commandMethod");
            }
            if (parameterBindResults == null)
            {
                throw new ArgumentNullException("parameterBindResults");
            }

            var bindingErrors = new Dictionary <string, Exception>();
            var builder       = new StringBuilder();

            builder.AppendFormat("Invalid parameters for command {0}(", commandMethod.Name);
            foreach (var parameterBindResult in parameterBindResults)
            {
                if (parameterBindResult.Parameter.IsOptional)
                {
                    builder.Append("[");
                }
                builder.Append(parameterBindResult.Parameter.Name);
                if (parameterBindResult.Parameter.IsOptional)
                {
                    builder.Append("]");
                }
                var isLast = parameterBindResult == parameterBindResults[parameterBindResults.Length - 1];
                if (isLast)
                {
                    builder.Append(")");
                }
                else
                {
                    builder.Append(", ");
                }
            }
            builder.AppendLine(":");
            foreach (var parameterBindResult in parameterBindResults)
            {
                builder.Append("\t").Append(parameterBindResult.Parameter.Name).Append(": ");
                if (parameterBindResult.IsSuccess)
                {
                    var value = TypeConvert.ToString(parameterBindResult.Value) ?? "<null>";
                    if (value.Length > 32)
                    {
                        builder.Append(value.Substring(0, 32)).AppendLine("...");
                    }
                    else
                    {
                        builder.AppendLine(value);
                    }
                }
                else
                {
                    bindingErrors[parameterBindResult.Parameter.Name] = parameterBindResult.Error;

                    var errorMessage  = parameterBindResult.Error.Message;
                    var parameterType = parameterBindResult.Parameter.ParameterType;
                    parameterType = Nullable.GetUnderlyingType(parameterType) ?? parameterType;
                    builder.Append("(").Append(parameterType.Name).Append(") ");
                    if (parameterBindResult.Error is FormatException && parameterBindResult.Value != null)
                    {
                        var value = TypeConvert.ToString(parameterBindResult.Value) ?? "<null>";
                        builder.Append(errorMessage)
                        .Append(" Value: '");
                        if (value.Length > 32)
                        {
                            builder.Append(value.Substring(0, 32)).Append("...");
                        }
                        else
                        {
                            builder.Append(value);
                        }
                        builder.AppendLine("'.");
                    }
                    else
                    {
                        builder.AppendLine(errorMessage);
                    }
                }
            }

            var error = new CommandLineException(builder.ToString());

            error.Data["method"] = commandMethod.Name;
#if !NETSTANDARD1_3
            error.Data["methodToken"] = commandMethod.MetadataToken;
#endif
            error.Data["bindingErrors"] = bindingErrors;
            return(error);
        }