/// <summary> /// Gets a list of expected command line arguments for the given data object. /// </summary> /// <param name="type">The data object type.</param> /// <returns>List of expected command line arguments.</returns> private static IList <CommandLineMemberInfo> Examine(Type type) { List <CommandLineMemberInfo> result = new List <CommandLineMemberInfo>(); foreach (MemberInfo member in type.GetMembers()) { CommandLineAttribute[] attributes = (CommandLineAttribute[])member.GetCustomAttributes(typeof(CommandLineAttribute), true); if (attributes == null || attributes.Length == 0) { continue; } CommandLineMemberInfo info = new CommandLineMemberInfo(); info.MemberInfo = member; info.ShortArgumentName = attributes[0].ShortName; info.LongArgumentName = attributes[0].LongName; info.HelpText = attributes[0].HelpText; info.Required = attributes[0].Required; if (member is FieldInfo) { FieldInfo fieldInfo = (FieldInfo)member; info.ArgumentType = fieldInfo.FieldType; } else if (member is PropertyInfo) { PropertyInfo propertyInfo = (PropertyInfo)member; info.ArgumentType = propertyInfo.PropertyType; } result.Add(info); } result.Sort(); return(result); }
/// <summary> /// Parses command line arguments into the given data object. /// </summary> /// <remarks> /// Members of the given data object should be marked with instances of CommandLineAttribute to define parsing behaviour. /// </remarks> /// <param name="dataObject">The data object.</param> /// <param name="args">Arguments to parse.</param> public static void Parse(object dataObject, string[] args) { ICommandLineArguments helper = dataObject as ICommandLineArguments; IList <CommandLineMemberInfo> members = Examine(dataObject); IList <CommandLineMemberInfo> requiredMembers = new List <CommandLineMemberInfo>(members.Where(m => m.Required)); Dictionary <string, CommandLineMemberInfo> shortNames = new Dictionary <string, CommandLineMemberInfo>(); Dictionary <string, CommandLineMemberInfo> longNames = new Dictionary <string, CommandLineMemberInfo>(); foreach (CommandLineMemberInfo member in members) { shortNames[member.ShortArgumentName] = member; longNames[member.LongArgumentName] = member; } if (helper != null) { helper.Initialize(); } for (int i = 0; i < args.Length; i++) { string name = args[i].ToLowerInvariant(); CommandLineMemberInfo member; if (name.StartsWith("--")) { string longName = name.Substring(2); longNames.TryGetValue(longName, out member); } else if (name.StartsWith("-")) { string shortName = name.Substring(1); shortNames.TryGetValue(shortName, out member); } else { member = null; } if (member == null) { throw new Exception(string.Format("Unrecognized command line option: {0}", name)); } try { if (member.ArgumentType == typeof(bool)) { SetValue(dataObject, member.MemberInfo, true); } else if (member.ArgumentType == typeof(int) || member.ArgumentType == typeof(long)) { long value = long.Parse(args[++i]); SetValue(dataObject, member.MemberInfo, true); } else if (member.ArgumentType == typeof(uint) || member.ArgumentType == typeof(ulong)) { ulong value = ulong.Parse(args[++i]); SetValue(dataObject, member.MemberInfo, true); } else if (member.ArgumentType == typeof(string)) { SetValue(dataObject, member.MemberInfo, args[++i]); } } catch { throw new Exception(string.Format("Badly formatted command line option: {0}", name)); } requiredMembers.Remove(member); } if (requiredMembers.Count > 0) { StringBuilder missingArguments = new StringBuilder(); missingArguments.Append("Missing required command line option(s): "); for (int i = 0; i < requiredMembers.Count; i++) { if (i > 0) { missingArguments.Append(", "); } CommandLineMemberInfo member = requiredMembers[i]; missingArguments.AppendFormat("--{0} (-{1})", member.LongArgumentName, member.ShortArgumentName); } throw new Exception(missingArguments.ToString()); } if (helper != null) { helper.Validate(); } }