using System; using System.Collections.Generic; using System.Collections; using System.Reflection; using ln.logging; using System.ComponentModel; namespace ln.types { public class Argument { public char Short { get; } public String Long { get; } public bool NeedsValue { get; } public bool HasValue => Value != null; public String Value { get; set; } public int IntegerValue => int.Parse(Value); public double DoubleValue => double.Parse(Value); public bool IsSet { get; set; } public Argument(char shortName, string longName) { Short = shortName; Long = longName; NeedsValue = false; } public Argument(char shortName, string longName, int defaultValue) : this(shortName, longName, defaultValue.ToString()) { } public Argument(char shortName, string longName, double defaultValue) : this(shortName, longName, defaultValue.ToString()) { } public Argument(char shortName, string longName, string defaultValue) { Short = shortName; Long = longName; NeedsValue = true; Value = defaultValue; } } /// /// Argument container. /// /// /// This class parses command line arguments to a list of predefined well known arguments. /// Remaining arguments will be found in AdditionalArguments. /// /// ArgumentContainer also provides a global command line option: /// --change-static typename fieldname value /// It may be used multiple times on the command line. /// It will load the type referenced by the qualified name typename and try to set the static field fieldname to value. /// value will be casted to field type via Convert.ChangeType(...) /// public class ArgumentContainer { List arguments; List additionalArguments; public string[] AdditionalArguments => additionalArguments.ToArray(); public ArgumentContainer() { arguments = new List(); additionalArguments = new List(); } public ArgumentContainer(IEnumerable argumentDefinitions) : this() { arguments.AddRange(argumentDefinitions); } public Argument this[string longName] { get { if (longName == null) throw new ArgumentNullException(nameof(longName)); foreach (Argument argument in arguments) { if (longName.Equals(argument.Long)) return argument; } throw new KeyNotFoundException(); } } public Argument this[char shortName] { get { if (shortName == 0) throw new ArgumentNullException(nameof(shortName)); foreach (Argument argument in arguments) { if (shortName.Equals(argument.Short)) return argument; } throw new KeyNotFoundException(); } } public bool Contains(string longName) { if (longName != null) foreach (Argument argument in arguments) { if (longName.Equals(argument.Long)) return true; } return false; } public bool Contains(char shortName) { if (shortName == (char)0) return false; foreach (Argument argument in arguments) { if (shortName.Equals(argument.Short)) return true; } return false; } public ArgumentContainer Add(Argument argument) { if (Contains(argument.Short) || Contains(argument.Long)) throw new ArgumentException(nameof(argument),String.Format("0x{0:x} / {1}",(int)argument.Short,argument.Long)); arguments.Add(argument); return this; } public ArgumentContainer Add(char shortName) => Add(new Argument(shortName, null)); public ArgumentContainer Add(string longName) => Add(new Argument((char)0, longName)); public ArgumentContainer Add(char shortName, string longName) => Add(new Argument(shortName, longName)); public ArgumentContainer Add(char shortName, string longName, string defaultValue) => Add(new Argument(shortName, longName, defaultValue)); public ArgumentContainer Add(int shortName, string longName, string defaultValue) => Add(new Argument((char)shortName, longName, defaultValue)); public void Parse(IEnumerable args) { Queue q = new Queue(args); while (q.Count > 0) { string currentOption = q.Dequeue(); if (currentOption[0].Equals('-')) { if (currentOption[1].Equals('-')) { String aname = currentOption.Substring(2); if (aname.Equals("change-static")) { string typeName = q.Dequeue(); string fieldName = q.Dequeue(); string value = q.Dequeue(); ChangeStatic(typeName, fieldName, value); } else { Argument argument = this[aname]; argument.IsSet = true; if (argument.NeedsValue) argument.Value = q.Dequeue(); } } else { foreach (char option in currentOption.Substring(1)) { Argument argument = this[option]; argument.IsSet = true; if (argument.NeedsValue) argument.Value = q.Dequeue(); } } } else { additionalArguments.Add(currentOption); } } } public void ChangeStatic(string typeName,string fieldname,string value) { Type type = Type.GetType(typeName); Logging.Log(LogLevel.INFO, "ArgumentContainer: ChangeStatic: Type: {0}",type); FieldInfo fieldInfo = type.GetField(fieldname, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); Logging.Log(LogLevel.INFO, "ArgumentContainer: ChangeStatic: Field: {0} {1}", fieldname, fieldInfo); object castValue = Convert.ChangeType(value, fieldInfo.FieldType); fieldInfo.SetValue(null,castValue); } } }