Пример #1
0
 public ArgumentMember(ArgumentCommandLineOptionAttribute argumentCommandLineOptionAttribute, MemberInfo memberInfo)
 {
     this.argumentCommandLineOptionAttribute = argumentCommandLineOptionAttribute;
     this.memberInfo = memberInfo;
 }
Пример #2
0
        /// <summary>
        /// Parses the command line for a particular type
        /// </summary>
        /// <param name="type">The type to parse against.</param>
        /// <param name="commandLineComplete">The command line to parse.</param>
        /// <returns>A ParseForTypeResults object that contains appliable command line options</returns>
        public ParseForTypeResults ParseForType(string commandLineComplete, Type type)
        {
            // Match executable portion of command line
            Regex commandLineExecutableRegex = new Regex("(^[^ \"]+)|(\"[^\"]+\")");
            Match commandLineExecutableMatch = commandLineExecutableRegex.Match(commandLineComplete);

            // Check executable part recognition
            if (!commandLineExecutableMatch.Success || commandLineExecutableMatch.Index != 0)
            {
                throw new Exception("Unable to recognise executable command line part");
            }

            // Get command line parts
            // string commandLineExecutable = commandLineComplete.Substring(0, commandLineExecutableMatch.Length);
            string commandLineArguments = commandLineComplete.Substring(commandLineExecutableMatch.Length);

            // Regular expression option for
            RegexOptions regexOptions = RegexOptions.ExplicitCapture;

            // Get the members of the config type
            MemberInfo[] memberInfos = type.FindMembers(
                NamedCommandLineOptionAttribute.memberTypes,
                NamedCommandLineOptionAttribute.bindingFlags,
                Type.FilterName,
                "*");

            // Construct member/regexp dictionary
            Dictionary <NamedCommandLineOptionAttribute, MemberInfo> memberAttributes =
                new Dictionary <NamedCommandLineOptionAttribute, MemberInfo>();
            List <MemberInfo>     requiredCommandLineOptionMembers = new List <MemberInfo>();
            MemberInfo            argumentsMemberInfo = null;
            List <ArgumentMember> argumentMembers     = new List <ArgumentMember>();

            // Walk thru members to find those marked with named option attribute
            foreach (MemberInfo memberInfo in memberInfos)
            {
                // Add named options to memberAttributes dictionary
                NamedCommandLineOptionAttribute[] namedCommandLineOptionAttributes =
                    Attribute.GetCustomAttributes(memberInfo, typeof(NamedCommandLineOptionAttribute)) as
                    NamedCommandLineOptionAttribute[];
                if (namedCommandLineOptionAttributes != null && namedCommandLineOptionAttributes.Length != 0)
                {
                    foreach (
                        NamedCommandLineOptionAttribute namedCommandLineOptionAttribute in
                        namedCommandLineOptionAttributes)
                    {
                        memberAttributes.Add(namedCommandLineOptionAttribute, memberInfo);
                    }
                }

                // Add required members to requiredCommandLineOptionMembers
                RequiredCommandLineOptionAttribute requiredCommandLineOptionAttribute =
                    Attribute.GetCustomAttribute(memberInfo, typeof(RequiredCommandLineOptionAttribute)) as
                    RequiredCommandLineOptionAttribute;
                if (requiredCommandLineOptionAttribute != null)
                {
                    requiredCommandLineOptionMembers.Add(memberInfo);
                }

                // Find default arguments property
                ArgumentsCommandLineOptionAttribute argumentsCommandLineOptionAttribute =
                    Attribute.GetCustomAttribute(memberInfo, typeof(ArgumentsCommandLineOptionAttribute)) as
                    ArgumentsCommandLineOptionAttribute;
                if (argumentsCommandLineOptionAttribute != null)
                {
                    if (argumentsMemberInfo != null)
                    {
                        throw new Exception("More than one arguments member");
                    }

                    argumentsMemberInfo = memberInfo;
                }

                // Add set arguements
                ArgumentCommandLineOptionAttribute argumentCommandLineOptionAttribute =
                    Attribute.GetCustomAttribute(memberInfo, typeof(ArgumentCommandLineOptionAttribute)) as
                    ArgumentCommandLineOptionAttribute;
                if (argumentCommandLineOptionAttribute != null)
                {
                    argumentMembers.Add(new ArgumentMember(argumentCommandLineOptionAttribute, memberInfo));
                }
            }

            List <OptionMemberValue> optionMemberValues = new List <OptionMemberValue>();
            List <Match>             unmatched          = new List <Match>();

            Dictionary <KeyValuePair <NamedCommandLineOptionAttribute, MemberInfo>, Regex> memberAttributeRegexCache =
                new Dictionary <KeyValuePair <NamedCommandLineOptionAttribute, MemberInfo>, Regex>();

            while (commandLineArguments.Length > 0)
            {
                commandLineArguments = commandLineArguments.TrimStart();

                bool processedNamedArgument = false;
                foreach (KeyValuePair <NamedCommandLineOptionAttribute, MemberInfo> memberAttribute in memberAttributes)
                {
                    Regex memberAttributeRegex;

                    // Use cached Regex if possible
                    if (memberAttributeRegexCache.ContainsKey(memberAttribute))
                    {
                        memberAttributeRegex = memberAttributeRegexCache[memberAttribute];
                    }
                    else
                    {
                        memberAttributeRegex = new Regex(memberAttribute.Key.GetRegularExpression(this), regexOptions);
                        memberAttributeRegexCache.Add(memberAttribute, memberAttributeRegex);
                    }

                    Match match = memberAttributeRegex.Match(commandLineArguments);
                    if (match.Success)
                    {
                        // Save the Attribute, Member & match for later application
                        optionMemberValues.Add(new OptionMemberValue(memberAttribute.Key, memberAttribute.Value, match));

                        // Remove required attribute from required list
                        requiredCommandLineOptionMembers.Remove(memberAttribute.Value);

                        // Consume the argument
                        commandLineArguments   = commandLineArguments.Substring(match.Index + match.Length).TrimStart();
                        processedNamedArgument = true;
                    }
                }

                if (!processedNamedArgument)
                {
                    // Un-recognised argument
                    Match match = commandLineExecutableRegex.Match(commandLineArguments);
                    if (match.Success)
                    {
                        unmatched.Add(match);

                        // Consume the argument
                        commandLineArguments = commandLineArguments.Substring(match.Index + match.Length).TrimStart();
                    }
                    else
                    {
                        // Can't work out what to consume
                        throw new Exception("Can't work out what to consume");
                    }
                }
            }

            // Process unmatched arguements
            List <Match> arguements = new List <Match>();

            arguements.AddRange(unmatched);
            foreach (ArgumentMember argumentMember in argumentMembers)
            {
                int index = argumentMember.argumentCommandLineOptionAttribute.Index;
                if (index < 0)
                {
                    index = unmatched.Count + index + 1;
                }

                if (index < 1 || index > unmatched.Count)
                {
                    // Arguement out of index
                    continue;
                }

                requiredCommandLineOptionMembers.Remove(argumentMember.memberInfo);
                arguements.Remove(unmatched[index - 1]);
            }

            // Check for default unmatched argument bucket
            if (argumentsMemberInfo == null)
            {
                if (arguements.Count > 0)
                {
                    // throw new Exception("Arguements with nowhere to go");
                    return(null);
                }
            }
            else
            {
                requiredCommandLineOptionMembers.Remove(argumentsMemberInfo);
            }

            // Check if we're setting all required members
            if (requiredCommandLineOptionMembers.Count != 0)
            {
                return(null);
            }

            // Check for duplicate set options
            List <MemberInfo> members = new List <MemberInfo>();

            foreach (OptionMemberValue optionMemberValue in optionMemberValues)
            {
                if (members.Contains(optionMemberValue.memberInfo))
                {
                    return(null);
                }

                members.Add(optionMemberValue.memberInfo);
            }

            // All looks good, create config object
            return(new ParseForTypeResults(
                       type,
                       optionMemberValues,
                       unmatched,
                       argumentsMemberInfo,
                       argumentMembers));
        }