183 lines
7.6 KiB
C#
183 lines
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
|
|
namespace ln.application
|
|
{
|
|
/// <summary>
|
|
/// Argument container.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This class parses command line arguments to a list of predefined well known arguments.
|
|
/// Remaining arguments will be found in <c>AdditionalArguments</c>.
|
|
///
|
|
/// <c>ArgumentContainer</c> also provides a global command line option:
|
|
/// --change-static <para>typename</para> <para>fieldname</para> <para>value</para>
|
|
/// It may be used multiple times on the command line.
|
|
/// It will load the type referenced by the qualified name <para>typename</para> and try to set the static field <para>fieldname</para> to <para>value</para>.
|
|
/// <para>value</para> will be casted to field type via Convert.ChangeType(...)
|
|
/// </remarks>
|
|
public class ArgumentContainer
|
|
{
|
|
private Dictionary<char, IArgument> shortOptionArguments = new Dictionary<char, IArgument>();
|
|
private Dictionary<string, IArgument> longOptionArguments = new Dictionary<string, IArgument>();
|
|
|
|
public ArgumentContainer()
|
|
{
|
|
}
|
|
public ArgumentContainer(IEnumerable<Argument> 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<IArgument> 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<string> args)
|
|
{
|
|
List<string> unusedArguments = new List<string>();
|
|
|
|
Queue<string> q = new Queue<string>(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<T>(string[] arguments)
|
|
{
|
|
ArgumentContainer argumentContainer = new ArgumentContainer();
|
|
argumentContainer.AddStaticOptions(typeof(T));
|
|
return argumentContainer.Parse(arguments);
|
|
}
|
|
public static void ApplyArguments<T>(ref string[] arguments)
|
|
{
|
|
arguments = ApplyArguments<T>(arguments);
|
|
}
|
|
|
|
public static string[] ApplyArguments<T>(T instance,string[] arguments)
|
|
{
|
|
ArgumentContainer argumentContainer = new ArgumentContainer();
|
|
argumentContainer.AddOptions(instance);
|
|
return argumentContainer.Parse(arguments);
|
|
}
|
|
public static void ApplyArguments<T>(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<StaticArgumentAttribute>() != null)
|
|
Add(new FieldArgument(fieldInfo, fieldInfo.GetCustomAttribute<StaticArgumentAttribute>()));
|
|
}
|
|
foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
|
|
{
|
|
if (propertyInfo.GetCustomAttribute<StaticArgumentAttribute>() != null)
|
|
Add(new PropertyArgument(propertyInfo, propertyInfo.GetCustomAttribute<StaticArgumentAttribute>()));
|
|
}
|
|
|
|
return this;
|
|
}
|
|
public ArgumentContainer AddOptions<T>(T instance)
|
|
{
|
|
foreach (FieldInfo fieldInfo in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
|
{
|
|
if (fieldInfo.GetCustomAttribute<StaticArgumentAttribute>() != null)
|
|
Add(new FieldArgument(instance, fieldInfo));
|
|
}
|
|
foreach (PropertyInfo propertyInfo in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
|
{
|
|
if (propertyInfo.GetCustomAttribute<StaticArgumentAttribute>() != null)
|
|
Add(new PropertyArgument(instance, propertyInfo));
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
public ArgumentContainer AddStaticOptions<T>() => 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);
|
|
}
|
|
}
|
|
}
|