/// <summary>
        ///  Initializes a new <see cref="CmdContextAttribute" />
        /// </summary>
        /// <param name="name">the name of the newly created context</param>
        /// <param name="description">The description of the context, defaults to null</param>
        /// <param name="longDescription">
        ///  The extended description of the context, each item of the array representing a paragraph, defaults
        ///  to null
        /// </param>
        /// <param name="shortForm">A shortform for this context</param>
        /// <param name="defaultActionPreset">
        ///  The preset for the <see cref="ContextDefaultAction" />, aka the action to run when no further arguments are
        ///  supplied
        /// </param>
        /// <exception cref="InvalidCLIConfigurationException">When the CLI is not configured correctly</exception>
        public CmdContextAttribute([NotNull] string name, string description = null, string[] longDescription = null,
                                   string shortForm = null, ContextDefaultActionPreset defaultActionPreset    = ContextDefaultActionPreset.Help)
        {
#if DEBUG
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new InvalidCLIConfigurationException("A name is required for any context",
                                                           new ArgumentException("Value cannot be null or whitespace.", nameof(name)));
            }

            if (name.IndexOfAny(IllegalCharactersInName) != -1)
            {
                throw new InvalidCLIConfigurationException("The name contains at least one illegal character ",
                                                           new ArgumentException("Illegal name", nameof(name)));
            }
#endif
            switch (defaultActionPreset)
            {
            case ContextDefaultActionPreset.Help:
                DefaultAction = ContextDefaultAction.PrintHelp();
                break;

            case ContextDefaultActionPreset.Exit:
                DefaultAction = ContextDefaultAction.Exit();
                break;

            case ContextDefaultActionPreset.Interactive:
                DefaultAction = ContextDefaultAction.InteractiveInterpreter();
                break;

            default:
                throw new InvalidCLIConfigurationException("Invalid default action preset provided",
                                                           new ArgumentOutOfRangeException(nameof(defaultActionPreset), defaultActionPreset, null));
            }

            Name = name;
            if (longDescription is null && !(description is null))
            {
                longDescription = new string[] { description };
            }

            LongDescription = longDescription;
            Description     = description;
            ShortForm       = shortForm;
        }
        /// <summary>
        ///  Loads the context if not loaded yet
        /// </summary>
        public void Load()
        {
            if (!_loaded)
            {
                SubCtx       = new List <CmdContextAttribute>();
                CtxActions   = new List <CmdActionAttribute>();
                CfgProviders = new List <CmdConfigurationProviderAttribute>();
                //CtxParameters = new List<CmdParameterAttribute>();
                foreach (TypeInfo nestedSubcontext in UnderlyingType.DeclaredNestedTypes)
                {
                    var contextAttribute = nestedSubcontext.GetCustomAttribute <CmdContextAttribute>();
                    if (contextAttribute != null)
                    {
                        contextAttribute.UnderlyingType = nestedSubcontext;
                        contextAttribute.DefaultAction  = DefaultAction;
                        SubCtx.Add(contextAttribute);
                    }
                }

                foreach (PropertyOrFieldInfo propertyOrField in UnderlyingType.DeclaredPropertiesAndFields())
                {
                    /*var parameterAttribute = propertyOrField.MemberInfo.GetCustomAttribute<CmdParameterAttribute>();
                     * if (parameterAttribute != null) {
                     * parameterAttribute.UnderlyingParameter = propertyOrField;
                     * CtxParameters.Add(parameterAttribute);
                     * }*/

                    var configurationProviderAttribute =
                        propertyOrField.MemberInfo.GetCustomAttribute <CmdConfigurationProviderAttribute>();
                    if (!(configurationProviderAttribute is null))
                    {
                        configurationProviderAttribute.UnderlyingPropertyOrField = propertyOrField;
                        configurationProviderAttribute.Root =
                            configurationProviderAttribute.UnderlyingPropertyOrField.ValueType
                            .GetCustomAttribute <CmdConfigurationNamespaceAttribute>();
#if DEBUG
                        if (configurationProviderAttribute.Root is null)
                        {
                            throw new InvalidCLIConfigurationException(
                                      $"The type of the property/field \"{propertyOrField.Name}\", which is marked with a CmdConfigurationProviderAttribute, ({configurationProviderAttribute.UnderlyingPropertyOrField.ValueType}) has no CmdConfigurationNamespaceAttribute as required.");
                        }
#endif
                        CfgProviders.Add(configurationProviderAttribute);
                    }
                }

                foreach (MethodInfo methodInfo in UnderlyingType.DeclaredMethods)
                {
                    var actionAttribute = methodInfo.GetCustomAttribute <CmdActionAttribute>();
                    if (actionAttribute != null)
                    {
                        actionAttribute.UnderlyingMethod = methodInfo;
                        CtxActions.Add(actionAttribute);
                    }

                    var defaultActionAttribute = methodInfo.GetCustomAttribute <CmdDefaultActionAttribute>();
                    if (defaultActionAttribute != null)
                    {
                        if (methodInfo.GetParameters().Length == defaultActionAttribute.Parameters.Length)
                        {
                            DefaultAction = new ContextDefaultAction(() => methodInfo.Invoke(null, defaultActionAttribute.Parameters));
                        }
                        else if (methodInfo.GetParameters().Length == defaultActionAttribute.Parameters.Length + 1)
                        {
#if DEBUG
                            if (!methodInfo.GetParameters().Last().ParameterType.IsAssignableFrom(typeof(ContextInterpreter)))
                            {
                                throw new InvalidCLIConfigurationException($"In the type {UnderlyingType.FullName} you have set the method {methodInfo.Name}" +
                                                                           " to be the context's default action, but if the method takes one more parameter than provided by the attribute," +
                                                                           " the type of the last method parameter must be Assignable from typeof(ContextInterpreter)");
                            }
#endif
                            DefaultAction =
                                new ContextDefaultAction(interpreter: x =>
                                                         methodInfo.Invoke(null, defaultActionAttribute.Parameters.Append(x).ToArray()));
                        }
                        else
                        {
                            throw new InvalidCLIConfigurationException(
                                      $"In the type {UnderlyingType.FullName} you have set the method {methodInfo.Name}" +
                                      $" to be the context's default action, in the defining attribute you have supplied {defaultActionAttribute.Parameters.Length} parameters" +
                                      " but that count must be the count of parameters accepted by the method or on less. Neither was the case.");
                        }
                    }
                }

                _loaded = true;
            }
        }