Example #1
0
        internal void HandleEmptyArguments(object target)
        {
            //
            // *** registered empty handlers are called by the multi-parser
            //

            var definedEmptyHandlers      = Type.GetMethodsWith <EmptyAttribute>();
            var definedEmptyHandlersCount = definedEmptyHandlers.Count();

            Debug.Assert(definedEmptyHandlersCount <= 1);

            if (definedEmptyHandlersCount == 1)
            {
                var method = definedEmptyHandlers.First();

                VerifyMethodAndTarget(method, target);

                var obj = method.IsStatic ? null : target;

                // if it is a [Help] handler
                //
                if (method.HasAttribute <HelpAttribute>())
                {
                    var help = m_helpGenerator.GetHelp(this);

                    // method should execute because it was already passed validation
                    //
                    MethodInvoker.Invoke(method, obj, new[] { help });
                }
                else
                {
                    MethodInvoker.Invoke(method, obj, null);
                }

                // don't handle the default verb
                //
                return;
            }

            var defaultVerb = GetDefaultVerb();

            // if there is a default verb - execute it
            //
            if (defaultVerb != null)
            {
                // create an array of arguments that matches the method
                //
                var serviceProvider = CreateServiceProvider(target);
                var parameters      = ValuesFactory.CreateParameterValues(
                    defaultVerb,
                    target,
                    new Dictionary <string, string>(),
                    GetParameters(defaultVerb.MethodInfo),
                    serviceProvider);

                Execute(target, defaultVerb, parameters);
            }
        }
Example #2
0
        private int RunInternal(string[] args, object obj)
        {
            //
            // *** empty args are handled by the multi-parser
            //
            //

            Debug.Assert(args.Length > 0 && args.All(a => !string.IsNullOrEmpty(a)));

            // the first arg should be the verb, unless there is no verb and a default is used
            //
            var firstArg = args[0];

            if (HandleHelp(firstArg, obj))
            {
                return(MultiParser.ErrorCode);
            }

            var verb = firstArg;

            // a flag, in case there is no verb
            //
            var noVerb = false;

            // find the method by the given verb
            //
            var typeVerbs = GetVerbs()
                            .ToDictionary(v => v, v => GetParameters(v.MethodInfo).ToList());

            // arguments
            var notVerbs = args
                           .Where(a => a.StartsWith(ArgumentPrefixes))
                           .ToList();

            var globals = GetDefinedGlobals()
                          .Where(g => notVerbs.Any(a => a.Substring(1).StartsWith(g.Name.ToLowerInvariant())))
                          .ToList();

            var notVerbsNotGlobals = notVerbs
                                     .Where(a => globals.All(g => !a.Substring(1).StartsWith(g.Name.ToLowerInvariant())))
                                     .ToList();

            // find the method by name, parameter count and parameter names
            var methods = (
                from v in typeVerbs
                where v.Key.Names.Contains(verb.ToLowerInvariant())
                where v.Value.Count == notVerbs.Count
                select v
                ).ToList();

            Method method = SelectMethod(methods, notVerbs);

            // if arguments do not match parameter names, exclude globals
            methods = (
                from v in typeVerbs
                where v.Key.Names.Contains(verb.ToLowerInvariant())
                where v.Value.Count == notVerbsNotGlobals.Count
                select v
                ).ToList();

            if (method == null)
            {
                method = SelectMethod(methods, notVerbsNotGlobals);
            }

            // if arguments do not match parameters names, exclude optional parameters
            if (method == null)
            {
                const bool avoidOptionalParameters = false;
                method = SelectMethod(methods, notVerbsNotGlobals, avoidOptionalParameters);
            }

            // if arguments do not match parameter names, use only argument count (without globals)
            if (method == null)
            {
                method = methods.FirstOrDefault().Key;
            }

            // if nothing matches...
            if (method == null)
            {
                method = typeVerbs.FirstOrDefault(v => v.Key.Names.Contains(verb.ToLowerInvariant())).Key;
            }

            // if no method is found - a default must exist
            if (method == null)
            {
                // if there is a verb input but no method was found
                // AND
                // the first arg is not an input argument (doesn't start with "-" etc)
                //
                if (verb != null && !verb.StartsWith(ArgumentPrefixes))
                {
                    throw new VerbNotFoundException(verb);
                }

                method = typeVerbs.FirstOrDefault(v => v.Key.IsDefault).Key;

                // no default - error
                //
                if (method == null)
                {
                    throw new MissingDefaultVerbException();
                }

                noVerb = true;
            }

            // if there is a verb - skip the first arg
            //
            var inputArgs = MapArguments(noVerb ? args : args.Skip(1));

            HandleGlobals(inputArgs, obj);

            // a list of the available parameters
            //
            var paremetersList = GetParameters(method.MethodInfo);

            // a list of values, used when invoking the method
            //
            var parameterValues = ValuesFactory.CreateParameterValues(method, obj, inputArgs, paremetersList);

            ValidateVerbInput(method, parameterValues.Select(kvp => kvp.Value).ToList());

            // if some args weren't handled
            //
            if (inputArgs.Any())
            {
                throw new UnhandledParametersException(inputArgs);
            }

            return(Execute(obj, method, parameterValues));
        }
Example #3
0
        /// <summary>
        /// Handles any defined global parameter that has any input
        /// </summary>
        private void HandleDefinedGlobals(Dictionary <string, string> args, object obj)
        {
            var globals = GetDefinedGlobals();

            foreach (var method in globals)
            {
                var att = method.GetAttribute <GlobalAttribute>();

                var name = att.Name ?? method.Name;

                var allNames = new[] { name }.Union(att.Aliases.CommaSplit());

                var key = args.Keys.FirstOrDefault(
                    k => allNames.Any(
                        n => n.Equals(k, StringComparison.InvariantCultureIgnoreCase)));

                if (key != null)
                {
                    var parameters = method.GetParameters();

                    if (parameters.Length == 0)
                    {
                        MethodInvoker.Invoke(method, obj, null);
                    }
                    else if (parameters.Length == 1)
                    {
                        string stringValue;

                        if (args.TryGetValue(key, out stringValue))
                        {
                            var p = parameters.First();

                            var value = ValuesFactory.GetValueForParameter(p, p.ParameterType, key, stringValue);

                            // validation
                            //
                            if (value != null && p.HasAttribute <ValidationAttribute>())
                            {
                                var parameterValidators = p.GetAttributes <ValidationAttribute>().Select(a => a.GetValidator());

                                // all validators must pass
                                //
                                foreach (var validator in parameterValidators)
                                {
                                    validator.Validate(new ValueInfo(p.Name, p.ParameterType, value));
                                }
                            }

                            var validators = method.GetInterfaceAttributes <ICollectionValidation>().
                                             Select(a => a.GetValidator());

                            foreach (var validator in validators)
                            {
                                validator.Validate(new[]
                                {
                                    new ValueInfo(p.Name, p.ParameterType, value),
                                });
                            }

                            MethodInvoker.Invoke(method, obj, new[] { value });
                        }
                    }
                    else
                    {
                        throw new NotSupportedException(
                                  "Method {0} has more than one parameter and cannot be handled as a global handler".FormatWith(method.Name));
                    }

                    // remove it so later we'll see which ones were not handled
                    //
                    args.Remove(key);
                }
            }
        }