/// <summary> /// Parse given arguments. /// </summary> /// <param name="args">The arguments to parse.</param> /// <returns>Remaining arguments.</returns> public string[] Parse(string[] args) { List <string> remainingArgs = new List <string>(); bool lastSwitch = false; for (int i = 0; i < args.Length;) { if (lastSwitch) { remainingArgs.Add(args[i++]); } else { CommandLineSwitch clSwitch = GetBestMatch(args, i); if (clSwitch == null) { remainingArgs.Add(args[i++]); } else if (clSwitch.ParsedArgsCount == 0) { throw new CommandLineSwitchSyntaxException(args[i++]); } else { i += clSwitch.Commit(); lastSwitch = lastSwitch || clSwitch.EndMarkerSwitch; if (clSwitch.RemainingArg.Length > 0) { remainingArgs.Add(clSwitch.RemainingArg); } } } } return(remainingArgs.ToArray()); }
/// <summary> /// Get the switch that best matches given arguments. /// </summary> /// <param name="args">The arguments array to parse.</param> /// <param name="startIndex">The index into the <paramref name="args"/> array where to start parsing.</param> /// <returns>The <see cref="CommandLineSwitch"/> that best matches given arguments</returns> public CommandLineSwitch GetBestMatch(string[] args, int startIndex) { CommandLineSwitch bestMatchSwitch = null; foreach (CommandLineSwitch item in SwitchesOrderedByType) { item.Parse(args, startIndex); if (item.ParsedLength == 0) { if (item.EndMarkerSwitch) { return(item); } continue; } if (bestMatchSwitch == null || item.ParsedLength > bestMatchSwitch.ParsedLength || item.ParsedLength == bestMatchSwitch.ParsedLength && item.NameMatchExactly && !bestMatchSwitch.NameMatchExactly) { bestMatchSwitch = item; } else if (item.NameMatchExactly == bestMatchSwitch.NameMatchExactly && item.ParsedLength == bestMatchSwitch.ParsedLength) { throw new CommandLineSwitchAmbiguousException(item.ParsedName, new string[] { item.Name, bestMatchSwitch.Name }); } } return(bestMatchSwitch); }
/// <summary> /// Add command line switches for given <paramref name="objectWithSwitchAttributes"/> type. /// </summary> /// <param name="objectWithSwitchAttributes">The attributed object from which the switches will be created</param> public void AddSwitchesForType(object objectWithSwitchAttributes) { foreach (CommandLineSwitch item in CommandLineSwitch.CreateSwitchesForType(objectWithSwitchAttributes)) { _switches[item.Name] = item; } }
internal static IEnumerable <CommandLineSwitch> CreateSwitchesForType(object objectWithSwitchAttributes) { Type type = objectWithSwitchAttributes.GetType(); MemberInfo[] members = type.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.SetProperty); for (int i = 0; i < members.Length; ++i) { object[] attributes = members[i].GetCustomAttributes(false); if (attributes.Length > 0) { CommandLineSwitch clSwitch = null; foreach (Attribute attribute in attributes) { if (attribute is CommandLineSwitchAttribute) { CommandLineSwitchAttribute switchAttribute = attribute as CommandLineSwitchAttribute; // Get the property information. We're only handling properties at the moment! if (members[i] is PropertyInfo) { PropertyInfo pi = (PropertyInfo)members[i]; string switchName = switchAttribute.Name; if (switchName == null || switchName.Length == 0) { switchName = pi.Name; } clSwitch = CommandLineSwitch.Create(switchName, switchAttribute.Description, pi.PropertyType); // Map in the Get/Set methods. clSwitch.SetMethod = pi.GetSetMethod(true); clSwitch.GetMethod = pi.GetGetMethod(true); clSwitch.Target = objectWithSwitchAttributes; // Can only handle a single switch for each property // (otherwise the parsing of aliases gets silly...) break; } } } // See if any aliases are required. We can only do this after // a switch has been registered and the framework doesn't make // any guarantees about the order of attributes, so we have to // walk the collection a second time. if (clSwitch != null) { foreach (Attribute attribute in attributes) { if (attribute is CommandLineSwitchAliasAttribute) { CommandLineSwitchAliasAttribute aliasAttribute = attribute as CommandLineSwitchAliasAttribute; clSwitch.AddAlias(aliasAttribute.Alias); } } } // Assuming we have an switch (that may or may not have aliases), add it to the collection of switches. if (clSwitch != null) { yield return(clSwitch); } } } }