/// <summary>Parse an XML configuration file matching this type.</summary>
        /// <param name="reader">An <see cref="XmlReader"/> which does the actual XML reading.</param>
        /// <param name="errors">[out] Returns a dictionary into which parse errors will be placed, where
        /// the key is the name of the argument the user provided, and the value is an error message
        /// describing that argument.</param>
        /// <returns>True if no errors were encountered, false otherwise.</returns>
        public bool ReadXml(XmlReader reader, out Dictionary<string, string> errors)
        {
            ConfigurationParseContext parseContext = new ConfigurationParseContext();
            if (this.ParseXmlConfigFileRaw(reader, parseContext))
            {
                // Check for all required
                List<PropertyInfo> missing = _required.FindAll(x => !parseContext.FlagsSetInConfigurationFile.Contains(x) && ((_fields[x].Type & FieldTypes.CliOnly) == FieldTypes.None)); // it's only missing if it's required *and* it's not CLI only
                foreach (PropertyInfo f in missing)
                {
                    parseContext.AddConfigurationError(f.Name, "missing required element");
                }
            }

            errors = parseContext.GenerateErrorDictionary();
            return errors.Count == 0;
        }
        /// <summary>Parses the argument list.</summary>
        /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception>
        /// <exception cref="TargetInvocationException">Thrown when a target invocation error condition
        /// occurs.</exception>
        /// <param name="defaultConfig">The default configuration file (this value can be null)</param>
        /// <param name="args">The array of arguments, similar to <c>argv</c>.</param>
        /// <param name="allowConfigFileLoad">If <c>true</c>, allows the parser to load data from XML
        /// configuration files and console response files; otherwise disallows these actions.</param>
        /// <param name="errors">[out] Returns a dictionary into which parse errors will be placed, where
        /// the key is the name of the argument the user provided, and the value is an error message
        /// describing that argument.</param>
        /// <returns>
        /// <c>true</c> if a program should continue running after this method returns, or <c>false</c>
        /// if the program should terminate. (For example, returns <c>true</c> when the parse is
        /// successful, <c>false</c> if an erroneous argument is provided, and <c>false</c> if the user
        /// requested usage with /?)
        /// </returns>
        public bool ParseArgs(string defaultConfig, IList<string> args, bool allowConfigFileLoad, out Dictionary<string, string> errors)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            ConfigurationParseContext parseContext = new ConfigurationParseContext();
            bool status = ParseArgsImpl(defaultConfig, args, allowConfigFileLoad, parseContext);

            // Set arrays to their parsed values
            foreach (KeyValuePair<PropertyInfo, List<object>> arrayArgumentValue in parseContext.MultipleUseArgumentValues)
            {
                List<object> o = arrayArgumentValue.Value;
                Array a = Array.CreateInstance(arrayArgumentValue.Key.PropertyType.GetElementType(), o.Count);
                for (int i = 0; i < o.Count; i++)
                {
                    a.SetValue(o[i], i);
                }

                try
                {
                    arrayArgumentValue.Key.SetValue(this, a, null);
                }
                catch (TargetInvocationException ex)
                {
                    if (ex.InnerException is ArgumentException)
                    {
                        parseContext.AddCommandLineError(arrayArgumentValue.Key.Name, ex.InnerException.Message);
                        status = false;
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            errors = parseContext.GenerateErrorDictionary();
            if (errors.Count != 0)
            {
                status = false;
            }

            // Validate is only run if we parsed OK
            if (status)
            {
                return this.Validate(errors);
            }

            return status;
        }