Beispiel #1
0
    private static IEnumerable <CommandParameter> GetParameters(CommandInfo command)
    {
        var result           = new List <CommandParameter>();
        var argumentPosition = 0;

        // We need to get parameters in order of the class where they were defined.
        // We assign each inheritance level a value that is used to properly sort the
        // arguments when iterating over them.
        IEnumerable <OrderedProperties> GetPropertiesInOrder()
        {
            var current   = command.SettingsType;
            var level     = 0;
            var sortOrder = 0;

            while (current.BaseType != null)
            {
                yield return(new OrderedProperties(level, sortOrder, current.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)));

                current = current.BaseType;

                // Things get a little bit complicated now.
                // Only consider a setting's base type part of the
                // setting, if there isn't a parent command that implements
                // the setting's base type. This might come back to bite us :)
                var currentCommand = command.Parent;
                while (currentCommand != null)
                {
                    if (currentCommand.SettingsType == current)
                    {
                        level--;
                        break;
                    }

                    currentCommand = currentCommand.Parent;
                }

                sortOrder--;
            }
        }

        var groups = GetPropertiesInOrder();

        foreach (var group in groups.OrderBy(x => x.Level).ThenBy(x => x.SortOrder))
        {
            var parameters = new List <CommandParameter>();

            foreach (var property in group.Properties)
            {
                if (property.IsDefined(typeof(CommandOptionAttribute)))
                {
                    var attribute = property.GetCustomAttribute <CommandOptionAttribute>();
                    if (attribute != null)
                    {
                        var option = BuildOptionParameter(property, attribute);

                        // Any previous command has this option defined?
                        if (command.HaveParentWithOption(option))
                        {
                            // Do we allow it to exist on this command as well?
                            if (command.AllowParentOption(option))
                            {
                                option.IsShadowed = true;
                                parameters.Add(option);
                            }
                        }
                        else
                        {
                            // No parent have this option.
                            parameters.Add(option);
                        }
                    }
                }
                else if (property.IsDefined(typeof(CommandArgumentAttribute)))
                {
                    var attribute = property.GetCustomAttribute <CommandArgumentAttribute>();
                    if (attribute != null)
                    {
                        var argument = BuildArgumentParameter(property, attribute);

                        // Any previous command has this argument defined?
                        // In that case, we should not assign the parameter to this command.
                        if (!command.HaveParentWithArgument(argument))
                        {
                            parameters.Add(argument);
                        }
                    }
                }
            }

            // Update the position for the parameters.
            foreach (var argument in parameters.OfType <CommandArgument>().OrderBy(x => x.Position))
            {
                argument.Position = argumentPosition++;
            }

            // Add all parameters to the result.
            foreach (var groupResult in parameters)
            {
                result.Add(groupResult);
            }
        }

        return(result);
    }