public EnumSwitchParser(PropertyInfo propertyInfo, CommandOptionSwitchAttribute optionSwitchAttribute) : base(propertyInfo, optionSwitchAttribute.CommandLiterals)
        {
            if (optionSwitchAttribute == null)
            {
                throw new ArgumentNullException(nameof(optionSwitchAttribute));
            }

            this._enumType    = optionSwitchAttribute.SwitchBaseType;
            this._validValues = Enum.GetNames(this._enumType);
        }
        private BaseSwitchPropertyParser BuildSwitchParser(PropertyInfo propertyInfo, CommandOptionSwitchAttribute optionSwitchAttribute, object[] otherAttributes)
        {
            if (optionSwitchAttribute.SwitchBaseType.IsEnum)
            {
                return(new EnumSwitchParser(propertyInfo, optionSwitchAttribute));
            }

            return(null);
        }
        private void BuildParsingProperties()
        {
            var properties = this._modelType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);

            foreach (var propertyInfo in properties)
            {
                if (propertyInfo.Name.Equals(nameof(CommandModel.RawParameters)))
                {
                    continue;
                }

                var attributes = propertyInfo.GetCustomAttributes(inherit: true);

                var optionNameAtt = attributes.SingleOrDefault(att => att is CommandOptionNameAttribute) as CommandOptionNameAttribute;
                if (optionNameAtt == null)
                {
                    throw new BadImplementationException($"Model property \"{propertyInfo.Name}\" misses mandatory {nameof(CommandOptionNameAttribute)}.", this._modelType);
                }

                var syntaxInfo = new SyntaxInfo(propertyInfo, optionNameAtt.Name);
                this._syntax.Add(syntaxInfo);

                // mandatory attribute
                var mandatoryAtt = attributes.SingleOrDefault(att => att is MandatoryAttribute) as MandatoryAttribute;
                if (mandatoryAtt != null && mandatoryAtt.IsParameterMandatory)
                {
                    //this._mandatoryProperties.Add(propertyInfo);
                    syntaxInfo.IsMandatory = true;
                }

                // description attribute
                var descriptionAtt = attributes.SingleOrDefault(att => att is CommandDescriptionAttribute) as CommandDescriptionAttribute;
                syntaxInfo.Description = descriptionAtt != null ? descriptionAtt.Description : "*** description not available ***";

                // Is Flag
                CommandOptionFlagAttribute optionFlagAtt = attributes.SingleOrDefault(att => att is CommandOptionFlagAttribute) as CommandOptionFlagAttribute;
                if (optionFlagAtt != null)
                {
                    var parser = new FlagPropertyParser(propertyInfo);
                    syntaxInfo.Literals   = optionFlagAtt.CommandLiterals;
                    syntaxInfo.OptionType = SyntaxOptionType.Flag;

                    foreach (var literal in optionFlagAtt.CommandLiterals)
                    {
                        var aLiteral = literal.Trim();

                        if (this._flagParsers.ContainsKey(aLiteral))
                        {
                            throw new BadImplementationException($"Flag argument literal \"{literal}\" has been declared more than once in the {this._modelType.FullName}.", this._modelType);
                        }

                        this._flagParsers.Add(aLiteral, parser);
                    }
                }

                // Is Switch
                CommandOptionSwitchAttribute optionSwitchAttribute = attributes.SingleOrDefault(att => att is CommandOptionSwitchAttribute) as CommandOptionSwitchAttribute;
                if (optionSwitchAttribute != null)
                {
                    var parser = this.BuildSwitchParser(propertyInfo, optionSwitchAttribute, attributes);
                    if (parser == null)
                    {
                        throw new BadImplementationException($"Could not find proper SwitchParser for property \"{propertyInfo.Name}\"", this._modelType);
                    }

                    if (optionSwitchAttribute.DefaultValue != null && syntaxInfo.IsMandatory)
                    {
                        throw new BadImplementationException($"When default value has been specified for property, it cannot be marked as mandatory. Bad declaration of property \"{propertyInfo.Name}\"", this._modelType);
                    }

                    syntaxInfo.Literals     = optionSwitchAttribute.CommandLiterals;
                    syntaxInfo.OptionType   = SyntaxOptionType.Switch;
                    syntaxInfo.SwitchValues = parser.GetValidValues().ToArray();
                    syntaxInfo.DefaultValue = optionSwitchAttribute.DefaultValue;

                    foreach (var literal in optionSwitchAttribute.CommandLiterals)
                    {
                        var aLiteral = literal.Trim();

                        if (this._switchParsers.ContainsKey(aLiteral))
                        {
                            throw new BadImplementationException($"Flag argument literal \"{literal}\" has been declared more than once in the {this._modelType.FullName}.", this._modelType);
                        }

                        this._switchParsers.Add(aLiteral, parser);
                    }
                }

                // Is Valued Flag - named, free value
                CommandOptionCustomValueSwitchAttribute optionCustomValueAtt = attributes.SingleOrDefault(att => att is CommandOptionCustomValueSwitchAttribute) as CommandOptionCustomValueSwitchAttribute;
                if (optionCustomValueAtt != null)
                {
                    var converter = this._convertersManager.GetConverterFor(propertyInfo.PropertyType);
                    if (converter == null)
                    {
                        throw new BadImplementationException($"Could not find required ArgumentConverter for type \"{propertyInfo.PropertyType.FullName}\" for ValueArgument \"{propertyInfo.Name}\".", this._modelType);
                    }

                    var parser = this.BuildValueOptionParser(propertyInfo, optionCustomValueAtt, attributes, converter);
                    if (parser == null)
                    {
                        throw new BadImplementationException($"Could not find proper SwitchParser for property \"{propertyInfo.Name}\"", this._modelType);
                    }

                    syntaxInfo.Literals   = optionCustomValueAtt.CommandLiterals;
                    syntaxInfo.OptionType = SyntaxOptionType.CustomValueSwitch;

                    // value parser is mainly compatible with switch-one
                    foreach (var literal in optionCustomValueAtt.CommandLiterals)
                    {
                        var aLiteral = literal.Trim();

                        if (this._switchParsers.ContainsKey(aLiteral))
                        {
                            throw new BadImplementationException($"Flag argument literal \"{literal}\" has been declared more than once in the {this._modelType.FullName}.", this._modelType);
                        }

                        this._switchParsers.Add(aLiteral, parser);
                    }
                }

                // Is unnamed argument
                CommandOptionSwitchlessAttribute nonPosAtt = attributes.SingleOrDefault(att => att is CommandOptionSwitchlessAttribute) as CommandOptionSwitchlessAttribute;
                if (nonPosAtt != null)
                {
                    syntaxInfo.OptionType = SyntaxOptionType.Switchless;

                    var converter = this._convertersManager.GetConverterFor(propertyInfo.PropertyType);
                    if (converter == null)
                    {
                        throw new BadImplementationException($"Could not find required ArgumentConverter for type \"{propertyInfo.PropertyType.FullName}\" for unnamed Argument at index [{nonPosAtt.ArgumentIndex}].", this._modelType);
                    }

                    this._switchlessParsers.Add(new SwitchlessPropertyParser(nonPosAtt.ArgumentIndex, propertyInfo, converter));
                }
            }
        }