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); } }
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)); }
/// <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); } } }