using System; using System.Collections.Generic; using System.Reflection; namespace ln.application { /// /// 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 { private Dictionary shortOptionArguments = new Dictionary(); private Dictionary longOptionArguments = new Dictionary(); public ArgumentContainer() { } public ArgumentContainer(IEnumerable argumentDefinitions) { AddRange(argumentDefinitions); } public ArgumentContainer(Type type) { AddStaticOptions(type); } public IArgument this[string optionName] => longOptionArguments[optionName]; public IArgument this[char option] => shortOptionArguments[option]; public bool Contains(string optionName) =>longOptionArguments.ContainsKey(optionName); public bool Contains(char option) => shortOptionArguments.ContainsKey(option); public ArgumentContainer AddRange(IEnumerable arguments) { foreach (IArgument argument in arguments) Add(argument); return this; } public ArgumentContainer Add(IArgument argument) { if (argument.OptionName > 0) shortOptionArguments.Add(argument.OptionName,argument); if (argument.LongOptionName != null) longOptionArguments.Add(argument.LongOptionName, 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 string[] Parse(IEnumerable args) { List unusedArguments = new List(); 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 if (Contains(aname)) { IArgument argument = this[aname]; argument.Value = argument.HasArgument ? q.Dequeue() : ""; } else { unusedArguments.Add("--" + aname); } } else { foreach (char option in currentOption.Substring(1)) { IArgument argument = this[option]; argument.Value = argument.HasArgument ? q.Dequeue() : ""; } } } else { unusedArguments.Add(currentOption); } } return unusedArguments.ToArray(); } public void Parse(ref string[] args) => args = Parse(args); public static string[] ApplyArguments(string[] arguments) { ArgumentContainer argumentContainer = new ArgumentContainer(); argumentContainer.AddStaticOptions(typeof(T)); return argumentContainer.Parse(arguments); } public static void ApplyArguments(ref string[] arguments) { arguments = ApplyArguments(arguments); } public static string[] ApplyArguments(T instance,string[] arguments) { ArgumentContainer argumentContainer = new ArgumentContainer(); argumentContainer.AddOptions(instance); return argumentContainer.Parse(arguments); } public static void ApplyArguments(T instance,ref string[] arguments) { arguments = ApplyArguments(instance, arguments); } public ArgumentContainer AddStaticOptions(Type type) { foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { if (fieldInfo.GetCustomAttribute() != null) Add(new FieldArgument(fieldInfo, fieldInfo.GetCustomAttribute())); } foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { if (propertyInfo.GetCustomAttribute() != null) Add(new PropertyArgument(propertyInfo, propertyInfo.GetCustomAttribute())); } return this; } public ArgumentContainer AddOptions(T instance) { foreach (FieldInfo fieldInfo in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) { if (fieldInfo.GetCustomAttribute() != null) Add(new FieldArgument(instance, fieldInfo)); } foreach (PropertyInfo propertyInfo in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) { if (propertyInfo.GetCustomAttribute() != null) Add(new PropertyArgument(instance, propertyInfo)); } return this; } public ArgumentContainer AddStaticOptions() => AddStaticOptions(typeof(T)); public void ChangeStatic(string typeName,string fieldname,string value) { Type type = Type.GetType(typeName); FieldInfo fieldInfo = type.GetField(fieldname, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object castValue = Convert.ChangeType(value, fieldInfo.FieldType); fieldInfo.SetValue(null,castValue); } } }