예제 #1
0
        private void AddSubcommandImpl <TSubCommand>(SubcommandAttribute subcommand)
            where TSubCommand : class, new()
        {
            if (App.Commands.Any(c => c.Name.Equals(subcommand.Name, StringComparison.OrdinalIgnoreCase)))
            {
                throw new InvalidOperationException(Strings.DuplicateSubcommandName(subcommand.Name));
            }

            var childApp = App.Command(subcommand.Name, subcommand.Configure);
            var builder  = new ReflectionAppBuilder <TSubCommand>(childApp);

            builder._bindResult = _bindResult;
            builder.Initialize();

            var subcommandProp = typeof(TTarget).GetTypeInfo().GetProperty("Subcommand", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (subcommandProp != null)
            {
                var setter = ReflectionHelper.GetPropertySetter(subcommandProp);
                builder.OnBind(o =>
                               setter.Invoke(this._target, o));
            }

            var parentProp = subcommand.CommandType.GetTypeInfo().GetProperty("Parent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (parentProp != null)
            {
                var setter = ReflectionHelper.GetPropertySetter(parentProp);
                builder.OnBind(o =>
                               setter.Invoke(o, this._target));
            }
        }
예제 #2
0
        private void AddRemainingArgsProperty(TypeInfo typeInfo)
        {
            var prop = typeInfo.GetProperty("RemainingArguments", PropertyBindingFlags);

            prop = prop ?? typeInfo.GetProperty("RemainingArgs", PropertyBindingFlags);
            if (prop == null)
            {
                return;
            }

            var setter = ReflectionHelper.GetPropertySetter(prop);

            if (prop.PropertyType == typeof(string[]))
            {
                OnBind(o
                       => setter(o, App.RemainingArguments.ToArray()));
                return;
            }

            if (!typeof(IReadOnlyList <string>).GetTypeInfo().IsAssignableFrom(prop.PropertyType))
            {
                throw new InvalidOperationException(Strings.RemainingArgsPropsIsUnassignable(typeInfo));
            }

            OnBind(o =>
                   setter(o, App.RemainingArguments));
        }
예제 #3
0
        private void AddArgument(PropertyInfo prop, ArgumentAttribute argumentAttr)
        {
            var argument = argumentAttr.Configure(prop);

            foreach (var attr in prop.GetCustomAttributes().OfType <ValidationAttribute>())
            {
                argument.Validators.Add(new AttributeValidator(attr));
            }

            argument.MultipleValues =
                prop.PropertyType.IsArray ||
                (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(prop.PropertyType) &&
                 prop.PropertyType != typeof(string));

            if (_argPropOrder.TryGetValue(argumentAttr.Order, out var otherProp))
            {
                throw new InvalidOperationException(
                          Strings.DuplicateArgumentPosition(argumentAttr.Order, prop, otherProp));
            }

            _argPropOrder.Add(argumentAttr.Order, prop);
            _argOrder.Add(argumentAttr.Order, argument);

            var setter = ReflectionHelper.GetPropertySetter(prop);

            if (argument.MultipleValues)
            {
                var collectionParser = CollectionParserProvider.Default.GetParser(prop.PropertyType);
                if (collectionParser == null)
                {
                    throw new InvalidOperationException(Strings.CannotDetermineParserType(prop));
                }

                OnBind(o =>
                       setter.Invoke(o, collectionParser.Parse(argument.Name, argument.Values)));
            }
            else
            {
                var parser = ValueParserProvider.Default.GetParser(prop.PropertyType);
                if (parser == null)
                {
                    throw new InvalidOperationException(Strings.CannotDetermineParserType(prop));
                }

                OnBind(o =>
                       setter.Invoke(o, parser.Parse(argument.Name, argument.Value)));
            }
        }
예제 #4
0
        private void AddSubcommandImpl <TSubCommand>(Type parent, SubcommandAttribute subcommand)
            where TSubCommand : class, new()
        {
            var parentApp = App;
            var childApp  = App.Command(subcommand.Name, subcommand.Configure);

            var builder = new ReflectionAppBuilder <TSubCommand>(childApp);

            builder.Initialize();

            var subcommandProp = parent.GetTypeInfo().GetProperty("Subcommand", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (subcommandProp != null)
            {
                var setter = ReflectionHelper.GetPropertySetter(subcommandProp);
                builder.OnBind(o =>
                {
                    if (parentApp.State is BindContext ctx)
                    {
                        setter.Invoke(ctx.Target, o);
                    }
                });
            }

            var parentProp = subcommand.CommandType.GetTypeInfo().GetProperty("Parent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (parentProp != null)
            {
                var setter = ReflectionHelper.GetPropertySetter(parentProp);
                builder.OnBind(o =>
                {
                    if (parentApp.State is BindContext ctx)
                    {
                        setter.Invoke(o, ctx.Target);
                    }
                });
            }
        }
예제 #5
0
        private void AddOption(OptionAttributeBase optionAttr, PropertyInfo prop)
        {
            CommandOption option;

            switch (optionAttr)
            {
            case HelpOptionAttribute h:
                option = h.Configure(App);
                break;

            case OptionAttribute o:
                option = o.Configure(App, prop);
                break;

            case VersionOptionAttribute v:
                option = v.Configure(App);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            foreach (var attr in prop.GetCustomAttributes().OfType <ValidationAttribute>())
            {
                option.Validators.Add(new AttributeValidator(attr));
            }

            if (option.OptionType == CommandOptionType.NoValue && prop.PropertyType != typeof(bool))
            {
                throw new InvalidOperationException(Strings.NoValueTypesMustBeBoolean);
            }

            if (option.ShortName != null)
            {
                if (_shortOptions.TryGetValue(option.ShortName, out var otherProp))
                {
                    throw new InvalidOperationException(
                              Strings.OptionNameIsAmbiguous(option.ShortName, prop, otherProp));
                }
                _shortOptions.Add(option.ShortName, prop);
            }

            if (option.LongName != null)
            {
                if (_longOptions.TryGetValue(option.LongName, out var otherProp))
                {
                    throw new InvalidOperationException(
                              Strings.OptionNameIsAmbiguous(option.LongName, prop, otherProp));
                }
                _longOptions.Add(option.LongName, prop);
            }

            var setter = ReflectionHelper.GetPropertySetter(prop);

            switch (option.OptionType)
            {
            case CommandOptionType.MultipleValue:
                var collectionParser = CollectionParserProvider.Default.GetParser(prop.PropertyType);
                if (collectionParser == null)
                {
                    throw new InvalidOperationException(Strings.CannotDetermineParserType(prop));
                }
                OnBind(o =>
                       setter.Invoke(o, collectionParser.Parse(option.LongName, option.Values)));
                break;

            case CommandOptionType.SingleValue:
                var parser = ValueParserProvider.Default.GetParser(prop.PropertyType);
                if (parser == null)
                {
                    throw new InvalidOperationException(Strings.CannotDetermineParserType(prop));
                }
                OnBind(o =>
                {
                    var value = option.Value();
                    if (value == null)
                    {
                        return;
                    }
                    setter.Invoke(o, parser.Parse(option.LongName, value));
                });
                break;

            case CommandOptionType.NoValue:
                OnBind(o =>
                       setter.Invoke(o, option.HasValue()));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }