/// <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; } }
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); }
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); }