// There is no license for this code. You are free to modify and redistribute it. Also, you can delete this comment. // Original source code: https://github.com/wertrain/command-line-parser-cs (Version 0.1) using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace CommandLineParser { /// /// Option attribute /// [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class Option : Attribute { /// /// Constructor /// public Option() { } /// /// Constructor /// /// public Option(string longName) { LongName = longName; } /// /// Constructor /// /// public Option(char shortName) { ShortName = shortName; } /// /// Constructor /// /// /// public Option(char shortName, string longName) { ShortName = shortName; LongName = longName; } /// /// long name command option /// public string LongName { get; private set; } /// /// short name command option /// public char ShortName { get; private set; } /// /// command option /// public string HelpText { get; set; } /// /// command option /// public bool Required { get; set; } } /// /// Results type of parse /// public enum ParserResultType { /// /// /// Parsed = 0, /// /// /// NotParsed } /// /// Results of parse /// /// public class ParserResult { /// /// /// /// internal ParserResult(ParserResultType tag, T value) { Tag = tag; Value = value; } /// /// /// public ParserResultType Tag { get; } /// /// /// public T Value { get; } } /// /// Utility for parser /// static class ParserUtility { /// /// /// /// /// /// public static T ConvertValue(this string input) { var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)); if (converter != null) { return (T)converter.ConvertFromString(input); } return default(T); } /// /// /// /// /// /// /// /// public static bool SetValueToProperty(PropertyInfo property, T value, string param) { switch (property.PropertyType.Name) { case "Boolean": if (string.IsNullOrEmpty(param)) { property.SetValue(value, true); } else { switch (param.ToLower()) { case "true": property.SetValue(value, true); return true; case "false": property.SetValue(value, false); return true; } } return false; case "Byte": property.SetValue(value, ConvertValue(param)); break; case "SByte": property.SetValue(value, ConvertValue(param)); break; case "Char": property.SetValue(value, ConvertValue(param)); break; case "Decimal": property.SetValue(value, ConvertValue(param)); break; case "Double": property.SetValue(value, ConvertValue(param)); break; case "Single": property.SetValue(value, ConvertValue(param)); break; case "Int32": property.SetValue(value, ConvertValue(param)); break; case "UInt32": property.SetValue(value, ConvertValue(param)); break; case "Int64": property.SetValue(value, ConvertValue(param)); break; case "UInt64": property.SetValue(value, ConvertValue(param)); break; case "Int16": property.SetValue(value, ConvertValue(param)); break; case "UInt16": property.SetValue(value, ConvertValue(param)); break; case "String": property.SetValue(value, param); return !string.IsNullOrEmpty(param); } return true; } } /// /// Arguments parser /// public class Parser { /// /// Help command /// private const string HelpLongName = "help"; /// /// Parse command line /// /// /// /// public static ParserResult Parse(string args) where T : new() { var enumerable = args.Split(); return Parse(enumerable); } /// /// Parse command line /// /// /// /// public static ParserResult Parse(IEnumerable args) where T : new() { if (args.Count() == 0) { ShowHelp(); return new ParserResult(ParserResultType.NotParsed, new T()); } var longNameDictionary = new Dictionary>(); var shortNameDictionary = new Dictionary>(); foreach (var property in typeof(T).GetProperties()) { var attributes = Attribute.GetCustomAttributes(property, typeof(Option)); foreach (Option option in attributes) { if (!string.IsNullOrWhiteSpace(option.LongName)) { longNameDictionary.Add(option.LongName, new Tuple(property.Name, option)); } if (option.ShortName != '\0') { shortNameDictionary.Add(option.ShortName, new Tuple(property.Name, option)); } } } var value = new T(); var resultTag = ParserResultType.Parsed; for (int i = 0, max = args.Count(); i < max; ++i) { var arg = args.ElementAt(i); Tuple pair = null; if (arg.StartsWith("--")) { string command = arg.Substring(2); if (command == HelpLongName) { ShowHelp(); return new ParserResult(ParserResultType.Parsed, new T()); } if (longNameDictionary.ContainsKey(command)) { pair = longNameDictionary[command]; } } else if (arg.StartsWith("-")) { string command = arg.Substring(1); if (command.Length != 1) { continue; } if (shortNameDictionary.ContainsKey(command[0])) { pair = shortNameDictionary[command[0]]; } } if (pair == null) { continue; } foreach (var property in typeof(T).GetProperties()) { if (pair.Item1 == property.Name) { string param = string.Empty; if (args.Count() > i + 1) { param = args.ElementAt(i + 1); } try { if (ParserUtility.SetValueToProperty(property, value, param)) { ++i; } } catch { resultTag = ParserResultType.NotParsed; } } } } return new ParserResult(resultTag, value); } /// /// Show help /// public static void ShowHelp() { int SpacePaddingSize = 12; var asm = Assembly.GetExecutingAssembly(); Console.WriteLine("{0} {1}", System.IO.Path.GetFileNameWithoutExtension(asm.Location), asm.GetName().Version); foreach (var property in typeof(T).GetProperties()) { var attributes = Attribute.GetCustomAttributes(property, typeof(Option)); foreach (Option attribute in attributes) { Console.Write("-{0}, --{1,-" + SpacePaddingSize + "} ", attribute.ShortName, attribute.LongName); if (attribute.Required) { Console.Write("[Required]"); } Console.WriteLine("{0}", attribute.HelpText); } } Console.WriteLine("--{0,-" + (SpacePaddingSize + HelpLongName.Length) + "} {1}", HelpLongName, "Display this help screen."); } } }