/// <summary>
        /// Parses and assigns a value to a field
        /// </summary>
        /// <param name="TargetObject">The target object to assign values to</param>
        /// <param name="Field">The field to assign the value to</param>
        /// <param name="ArgumentText">The full argument text</param>
        /// <param name="ValueText">Argument text</param>
        /// <param name="PreviousArgumentText">The previous text used to configure this field</param>
        /// <returns>True if the value was assigned to the field, false otherwise</returns>
        private static bool ApplyArgument(object TargetObject, FieldInfo Field, string ArgumentText, string ValueText, string PreviousArgumentText)
        {
            // The value type for items of this field
            Type ValueType = Field.FieldType;

            // Check if the field type implements ICollection<>. If so, we can take multiple values.
            Type CollectionType = null;

            foreach (Type InterfaceType in Field.FieldType.GetInterfaces())
            {
                if (InterfaceType.IsGenericType && InterfaceType.GetGenericTypeDefinition() == typeof(ICollection <>))
                {
                    ValueType      = InterfaceType.GetGenericArguments()[0];
                    CollectionType = InterfaceType;
                    break;
                }
            }

            // Try to parse the value
            object Value;

            if (!TryParseValue(ValueType, ValueText, out Value))
            {
                Log.TraceWarning("Unable to parse value for argument '{0}'.", ArgumentText);
                return(false);
            }

            // Try to assign values to the target field
            if (CollectionType == null)
            {
                // Check if this field has already been assigned to. Output a warning if the previous value is in conflict with the new one.
                if (PreviousArgumentText != null)
                {
                    object PreviousValue = Field.GetValue(TargetObject);
                    if (!PreviousValue.Equals(Value))
                    {
                        Log.TraceWarning("Argument '{0}' conflicts with '{1}'; ignoring.", ArgumentText, PreviousArgumentText);
                    }
                    return(false);
                }

                // Set the value on the target object
                Field.SetValue(TargetObject, Value);
                return(true);
            }
            else
            {
                // Call the 'Add' method on the collection
                CollectionType.InvokeMember("Add", BindingFlags.InvokeMethod, null, Field.GetValue(TargetObject), new object[] { Value });
                return(true);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets a list of ConfigFields for the given type
        /// </summary>
        /// <param name="TargetObjectType">Type to get configurable fields for</param>
        /// <returns>List of config fields for the given type</returns>
        static List <ConfigField> FindConfigFieldsForType(Type TargetObjectType)
        {
            List <ConfigField> Fields;

            lock (TypeToConfigFields)
            {
                if (!TypeToConfigFields.TryGetValue(TargetObjectType, out Fields))
                {
                    Fields = new List <ConfigField>();
                    if (TargetObjectType.BaseType != null)
                    {
                        Fields.AddRange(FindConfigFieldsForType(TargetObjectType.BaseType));
                    }
                    foreach (FieldInfo FieldInfo in TargetObjectType.GetFields(BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
                    {
                        IEnumerable <ConfigFileAttribute> Attributes = FieldInfo.GetCustomAttributes <ConfigFileAttribute>();
                        foreach (ConfigFileAttribute Attribute in Attributes)
                        {
                            // Copy the field
                            ConfigField Setter = new ConfigField();
                            Setter.FieldInfo = FieldInfo;
                            Setter.Attribute = Attribute;

                            // Check if the field type implements ICollection<>. If so, we can take multiple values.
                            foreach (Type InterfaceType in FieldInfo.FieldType.GetInterfaces())
                            {
                                if (InterfaceType.IsGenericType && InterfaceType.GetGenericTypeDefinition() == typeof(ICollection <>))
                                {
                                    MethodInfo MethodInfo = InterfaceType.GetRuntimeMethod("Add", new Type[] { InterfaceType.GenericTypeArguments[0] });
                                    Setter.AddElement  = (Target, Value) => { MethodInfo.Invoke(Setter.FieldInfo.GetValue(Target), new object[] { Value }); };
                                    Setter.ElementType = InterfaceType.GenericTypeArguments[0];
                                    break;
                                }
                            }

                            // Add it to the output list
                            Fields.Add(Setter);
                        }
                    }
                    TypeToConfigFields.Add(TargetObjectType, Fields);
                }
            }
            return(Fields);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Parse the options from the given command line into the given options, using CommandLineOption attributes.
        /// </summary>
        /// <param name="Args">The arguments to parse</param>
        /// <param name="Options">Object to receive the parsed options</param>
        /// <returns>True if all options were parsed, false otherwise</returns>
        public static bool Parse(string[] Args, object Options)
        {
            bool bResult = true;

            // Parse out all the arguments we can
            List <string> RemainingArgs = new List <string>(Args);

            foreach (FieldInfo Field in Options.GetType().GetFields())
            {
                CommandLineOptionAttribute OptionAttribute = Field.GetCustomAttribute <CommandLineOptionAttribute>();
                if (OptionAttribute != null)
                {
                    string Name = OptionAttribute.Name ?? Field.Name;
                    if (Field.FieldType == typeof(bool))
                    {
                        string Flag = String.Format("-{0}", Name);
                        if (RemainingArgs.RemoveAll(x => x.Equals(Flag, StringComparison.InvariantCultureIgnoreCase)) > 0)
                        {
                            Field.SetValue(Options, true);
                        }
                    }
                    else
                    {
                        string Prefix = String.Format("-{0}=", Name);

                        // Find all the values with this prefix
                        List <string> Values = new List <string>();
                        for (int Idx = 0; Idx < RemainingArgs.Count; Idx++)
                        {
                            if (RemainingArgs[Idx].StartsWith(Prefix, StringComparison.InvariantCultureIgnoreCase))
                            {
                                string Suffix = RemainingArgs[Idx].Substring(Prefix.Length);
                                if (OptionAttribute.Separator != 0)
                                {
                                    Values.AddRange(Suffix.Split(OptionAttribute.Separator));
                                }
                                else
                                {
                                    Values.Add(Suffix);
                                }
                                RemainingArgs.RemoveAt(Idx--);
                            }
                        }

                        // Check if the field type implements ICollection<>. If so, we can take multiple values.
                        Type CollectionType = null;
                        foreach (Type InterfaceType in Field.FieldType.GetInterfaces())
                        {
                            if (InterfaceType.IsGenericType && InterfaceType.GetGenericTypeDefinition() == typeof(ICollection <>))
                            {
                                CollectionType = InterfaceType;
                                break;
                            }
                        }

                        // Assign the values to the field
                        if (Values.Count == 0)
                        {
                            if (OptionAttribute.IsRequired)
                            {
                                Console.WriteLine("Missing parameter {0}...", Prefix);
                                bResult = false;
                            }
                        }
                        else
                        {
                            if (CollectionType == null)
                            {
                                if (Values.Count > 1)
                                {
                                    Console.WriteLine("Multiple values specified for {0}...", Prefix);
                                    bResult = false;
                                }
                                else if (Field.FieldType.IsEnum)
                                {
                                    try
                                    {
                                        object TypedValue = Enum.Parse(Field.FieldType, Values[0], true);
                                        Field.SetValue(Options, TypedValue);
                                    }
                                    catch (ArgumentException)
                                    {
                                        Console.WriteLine("Invalid argument for '{0}'. Expected {1}.", Name, String.Join("/", Enum.GetNames(Field.FieldType)));
                                        bResult = false;
                                    }
                                }
                                else
                                {
                                    object TypedValue = Convert.ChangeType(Values[0], Field.FieldType);
                                    Field.SetValue(Options, TypedValue);
                                }
                            }
                            else
                            {
                                foreach (string Value in Values)
                                {
                                    object TypedValue = Convert.ChangeType(Value, CollectionType.GenericTypeArguments[0]);
                                    CollectionType.InvokeMember("Add", BindingFlags.InvokeMethod, null, Field.GetValue(Options), new object[] { TypedValue });
                                }
                            }
                        }
                    }
                }
            }

            // Check there's nothing left over that we couldn't parse
            if (RemainingArgs.Count > 0)
            {
                foreach (string RemainingArg in RemainingArgs)
                {
                    Console.WriteLine("Invalid argument: {0}", RemainingArg);
                }
                bResult = false;
            }

            return(bResult);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Parses and assigns a value to a field
        /// </summary>
        /// <param name="Parameter">The parameter being parsed</param>
        /// <param name="Text">Argument text</param>
        /// <param name="TargetObject">The target object to assign values to</param>
        /// <param name="AssignedFieldToParameter">Maps assigned fields to the parameter that wrote to it. Used to detect duplicate and conflicting arguments.</param>
        static void AssignValue(Parameter Parameter, string Text, object TargetObject, Dictionary <FieldInfo, Parameter> AssignedFieldToParameter)
        {
            // Check if the field type implements ICollection<>. If so, we can take multiple values.
            Type CollectionType = null;

            foreach (Type InterfaceType in Parameter.FieldInfo.FieldType.GetInterfaces())
            {
                if (InterfaceType.IsGenericType && InterfaceType.GetGenericTypeDefinition() == typeof(ICollection <>))
                {
                    CollectionType = InterfaceType;
                    break;
                }
            }

            // Try to assign values to the target field
            if (CollectionType == null)
            {
                // Try to parse the value
                object Value;
                if (!TryParseValue(Parameter.FieldInfo.FieldType, Text, out Value))
                {
                    Log.WriteLine(LogEventType.Warning, "Invalid value for {0}... - ignoring {1}", Parameter.Prefix, Text);
                    return;
                }

                // Check if this field has already been assigned to. Output a warning if the previous value is in conflict with the new one.
                Parameter PreviousParameter;
                if (AssignedFieldToParameter.TryGetValue(Parameter.FieldInfo, out PreviousParameter))
                {
                    object PreviousValue = Parameter.FieldInfo.GetValue(TargetObject);
                    if (!PreviousValue.Equals(Value))
                    {
                        if (PreviousParameter.Prefix == Parameter.Prefix)
                        {
                            Log.WriteLine(LogEventType.Warning, "Conflicting {0} arguments - ignoring", Parameter.Prefix);
                        }
                        else
                        {
                            Log.WriteLine(LogEventType.Warning, "{0} conflicts with {1} - ignoring", Parameter.Prefix, PreviousParameter.Prefix);
                        }
                    }
                    return;
                }

                // Set the value on the target object
                Parameter.FieldInfo.SetValue(TargetObject, Value);
                AssignedFieldToParameter.Add(Parameter.FieldInfo, Parameter);
            }
            else
            {
                // Split the text into an array of values if necessary
                string[] ItemArray;
                if (Parameter.Attribute.ListSeparator == 0)
                {
                    ItemArray = new string[] { Text };
                }
                else
                {
                    ItemArray = Text.Split(Parameter.Attribute.ListSeparator);
                }

                // Parse each of the argument values separately
                foreach (string Item in ItemArray)
                {
                    object Value;
                    if (TryParseValue(CollectionType.GenericTypeArguments[0], Item, out Value))
                    {
                        CollectionType.InvokeMember("Add", BindingFlags.InvokeMethod, null, Parameter.FieldInfo.GetValue(TargetObject), new object[] { Value });
                    }
                    else
                    {
                        Log.WriteLine(LogEventType.Warning, "'{0}' is not a valid value for -{1}=... - ignoring", Item, Parameter.Prefix);
                    }
                }
            }
        }