/// <summary>
        /// Transform <see cref="CommandLineArguments"/> to list of string chunks. Chunks should be escaped(quoted) before combining them into one string.
        /// </summary>
        public string[] ToArray()
        {
            var count    = 0;
            var position = 0;

            foreach (var kv in this)
            {
                if (!int.TryParse(kv.Key, out position))
                {
                    if (kv.Value == null)
                    {
                        count++;                         // only parameter name
                    }
                    else if (kv.Value is IList <string> )
                    {
                        count += 1 + ((IList <string>)kv.Value).Count;                        // parameter name + values
                    }
                    else
                    {
                        count += 2;                         // parameter name + value
                    }
                }
                else
                {
                    if (kv.Value is IList <string> )
                    {
                        count += ((IList <string>)kv.Value).Count;                        // only values
                    }
                    else if (kv.Value != null)
                    {
                        count += 1;                         // only value
                    }
                }
            }

            var array = new string[count];
            var index = 0;

            foreach (var kv in this.OrderBy(kv => kv.Key, IntAsStringComparer.Default))
            {
                var valuesList = kv.Value as IList <string>;

                if (!int.TryParse(kv.Key, out position))
                {
                    array[index++] = string.Concat(CommandLine.ArgumentNamePrefix, kv.Key);
                }

                if (valuesList != null)
                {
                    valuesList.CopyTo(array, index);
                    index += valuesList.Count;
                }
                else if (kv.Value != null)
                {
                    array[index++] = TypeConvert.ToString(kv.Value);
                }
            }

            return(array);
        }
        /// <summary>
        /// Insert new positional argument and "push" other positional argument forward.
        /// </summary>
        public void InsertAt(int position, string value)
        {
            if (position < 0)
            {
                throw new ArgumentOutOfRangeException("position");
            }
            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentException("Value can't be empty or null.", "value");
            }

            var currentValue = default(object);
            var positionKey  = position.ToString();
            var hasCurrent   = this.TryGetValue(positionKey, out currentValue) && string.IsNullOrEmpty(TypeConvert.ToString(currentValue)) == false;

            this[positionKey] = value;

            while (hasCurrent)
            {
                value             = TypeConvert.ToString(currentValue);
                positionKey       = (++position).ToString();
                hasCurrent        = this.TryGetValue(positionKey, out currentValue) && string.IsNullOrEmpty(TypeConvert.ToString(currentValue)) == false;
                this[positionKey] = value;
            }
        }
예제 #3
0
        private static MethodBindResult BindMethod(Type type, string defaultMethodName, CommandLineArguments arguments)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (arguments == null)
            {
                throw new ArgumentNullException("arguments");
            }

            if (string.IsNullOrEmpty(defaultMethodName))
            {
                defaultMethodName = null;
            }

            var allMethods = type.GetTypeInfo().GetAllMethods().Where(IsValidCommandSignature).ToList();

            allMethods.Sort((x, y) => y.GetParameters().Length.CompareTo(x.GetParameters().Length));

            var methodName      = default(string);
            var bestMatchResult = default(MethodBindResult);

            if (arguments.ContainsKey("0"))
            {
                var newArguments = new CommandLineArguments(arguments);
                methodName = TypeConvert.ToString(newArguments["0"]);
                newArguments.RemoveAt(0);
                var result = BindMethod(allMethods, methodName, newArguments);
                if (result.IsSuccess)
                {
                    return(result);
                }

                bestMatchResult = result;
            }

            if (string.IsNullOrEmpty(defaultMethodName) == false)
            {
                methodName = defaultMethodName;
                var result = BindMethod(allMethods, defaultMethodName, arguments);
                if (result.IsSuccess)
                {
                    return(result);
                }

                bestMatchResult = bestMatchResult ?? result;
            }

            if (string.IsNullOrEmpty(methodName))
            {
                methodName = UnknownMethodName;
            }

            bestMatchResult = bestMatchResult ?? new MethodBindResult(methodName, MethodBindResult.EmptyFailedMethodBindings);

            return(bestMatchResult);
        }
예제 #4
0
        private static MethodBindResult BindMethod(Type type, string defaultMethodName, CommandLineArguments arguments)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (arguments == null)
            {
                throw new ArgumentNullException("arguments");
            }

            var methodName = defaultMethodName;

            if (arguments.ContainsKey("0"))
            {
                arguments  = new CommandLineArguments(arguments);
                methodName = TypeConvert.ToString(arguments["0"]);
                arguments.RemoveAt(0);
            }

            var candidate  = default(MethodInfo);
            var allMethods = type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);

            Array.Sort(allMethods, (x, y) => y.GetParameters().Length.CompareTo(x.GetParameters().Length));
            foreach (var method in allMethods)
            {
                if (string.Equals(method.Name, methodName, StringComparison.OrdinalIgnoreCase) == false || !method.IsStatic || method.ReturnType != typeof(int) || IsHidden(method))
                {
                    continue;
                }

                candidate = method;
                var parameters = method.GetParameters();
                var methodArgs = new object[parameters.Length];
                foreach (var parameter in parameters)
                {
                    var value = default(object);
                    if (TryBindParameter(parameter, arguments, out value) == false)
                    {
                        goto nextMethod;
                    }
                    methodArgs[parameter.Position] = value;
                }

                return(new MethodBindResult(method, methodArgs));

nextMethod:
                ;
            }

            return(new MethodBindResult(methodName, candidate));
        }
 /// <summary>
 /// Get positional argument.
 /// </summary>
 /// <param name="position">Zero-based position of argument.</param>
 /// <returns>Value of positional argument.</returns>
 public string this[int position]
 {
     get
     {
         return(TypeConvert.ToString(this.GetValueOrDefault(position.ToString())));
     }
     set
     {
         if (string.IsNullOrEmpty(value))
         {
             throw new ArgumentException("Value can't be empty or null.", "value");
         }
         this[position.ToString()] = value;
     }
 }
        /// <summary>
        /// Creates new instance of <see cref="CommandLineArguments"/> with <paramref name="arguments"/>.
        /// </summary>
        public CommandLineArguments(IEnumerable <string> arguments)
            : this()
        {
            if (arguments == null)
            {
                throw new ArgumentException("arguments");
            }

            foreach (var kv in ParseArguments(arguments))
            {
                var currentValue = default(object);
                if (this.TryGetValue(kv.Key, out currentValue))
                {
                    if (kv.Value == null)
                    {
                        continue;
                    }

                    // try to combine with existing value
                    if (currentValue == null)
                    {
                        this[kv.Key] = currentValue = new List <string>();
                    }
                    else if (currentValue is List <string> == false)
                    {
                        this[kv.Key] = currentValue = new List <string> {
                            TypeConvert.ToString(currentValue)
                        }
                    }
                    ;

                    var currentList = (List <string>)currentValue;
                    if (kv.Value is List <string> )
                    {
                        currentList.AddRange((List <string>)kv.Value);
                    }
                    else
                    {
                        currentList.Add(TypeConvert.ToString(kv.Value));
                    }
                }
                else
                {
                    this.Add(kv.Key, kv.Value);
                }
            }
        }
        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);
        }