internal VerbExecutionContext( Method method, object target, Dictionary<string, string> input) { Method = method; Target = target; Input = input; }
public DefaultVerbInvocation(string verb, Method verbMethod, List<object> parms, object target, IEnumerable<string> inputArgs, Dictionary<string, string> inputDictionary, Dictionary<string, string> unusedDictionary ) { Debug.Assert(verb != null); Debug.Assert(verbMethod != null); Debug.Assert(inputArgs != null); Debug.Assert(inputDictionary != null); InputArgs = new ReadOnlyCollection<string>(inputArgs.ToList()); InputDictionary = inputDictionary; UnusedDictionary = unusedDictionary ?? new Dictionary<string, string>(); var verbParms = parms ?? new List<object>(); Verb = verb; VerbMethod = verbMethod; VerbParameters = verbParms.AsReadOnly(); TargetObject = target; }
private PreVerbExecutionContext PreInterception( object target, Method method, ParameterAndValue[] parameters) { var preVerbExecutionContext = new PreVerbExecutionContext(method, target, parameters); // registered interceptors get top priority // if (m_registration.RegisteredPreVerbInterceptor != null) { m_registration.RegisteredPreVerbInterceptor(preVerbExecutionContext); } else { // try a defined verb interceptor // var preInterceptionMethods = Type.GetMethodsWith<PreVerbExecutionAttribute>(); if (preInterceptionMethods.Any()) { Debug.Assert(preInterceptionMethods.Count() == 1); var preInterceptionMethod = preInterceptionMethods.First(); MethodInvoker.Invoke(preInterceptionMethod, target, new[] { preVerbExecutionContext }); } else { // try a defined interceptor type // if (Type.HasAttribute<VerbInterception>()) { var interception = Type.GetAttribute<VerbInterception>(); var interceptor = (IPreVerbInterceptor)Activator.CreateInstance(interception.InterceptorType); interceptor.BeforeVerbExecution(preVerbExecutionContext); } } } return preVerbExecutionContext; }
private void PostInterception( object target, Method method, ParameterAndValue[] parameters, PreVerbExecutionContext preVerbExecutionContext, Exception verbException) { var postVerbExecutionContext = new PostVerbExecutionContext( method, target, parameters, preVerbExecutionContext.Cancel, verbException, preVerbExecutionContext.UserContext); // registered interceptors get top priority // if (m_registration.RegisteredPostVerbInterceptor != null) { m_registration.RegisteredPostVerbInterceptor(postVerbExecutionContext); } else { var postInterceptionMethods = Type.GetMethodsWith<PostVerbExecutionAttribute>(); // try a defined interceptor type // if (postInterceptionMethods.Any()) { Debug.Assert(postInterceptionMethods.Count() == 1); var postInterceptionMethod = postInterceptionMethods.First(); MethodInvoker.Invoke(postInterceptionMethod, target, new[] { postVerbExecutionContext }); } else { // try a defined interceptor type // if (Type.HasAttribute<VerbInterception>()) { var interception = Type.GetAttribute<VerbInterception>(); var interceptor = (IPostVerbInterceptor)Activator.CreateInstance(interception.InterceptorType); interceptor.AfterVerbExecution(postVerbExecutionContext); } } } }
private int Execute( object target, Method method, ParameterAndValue[] parameters) { // pre-interception // var preVerbExecutionContext = PreInterception(target, method, parameters); Exception verbException = null; try { // actual verb execution // if (!preVerbExecutionContext.Cancel) { // invoke the method with the list of parameters // MethodInvoker.Invoke(method.MethodInfo, target, parameters.Select(p => p.Value).ToArray()); } } catch (TargetInvocationException tex) { PreserveStackTrace(tex.InnerException); verbException = tex.InnerException; } catch (Exception ex) { verbException = ex; } finally { try { PostInterception(target, method, parameters, preVerbExecutionContext, verbException); } finally { if (verbException != null) { var rethrow = HandleError(verbException, target); if (rethrow) { throw verbException; } } } } return verbException == null ? MultiParser.SuccessCode : MultiParser.ErrorCode; }
private static void ValidateVerbInput(Method method, List<object> parameterValues) { var methodParameters = method.MethodInfo.GetParameters(); // validate all parameters // var validators = method.MethodInfo.GetInterfaceAttributes<ICollectionValidation>().Select(a => a.GetValidator()); if (validators.Any()) { var parametersAndValues = new List<ValueInfo>(); methodParameters.Each((p, i) => { parametersAndValues.Add(new ValueInfo(p.Name, p.ParameterType, parameterValues[i])); }); // all validators must pass // foreach (var validator in validators) { validator.Validate(parametersAndValues.ToArray()); } } }
public MissingRequiredArgumentException(Method method, string parameter) : base("Missing argument for required parameter '{0}'".FormatWith(parameter)) { Method = method; ParameterName = parameter; }
private (Method method, ParameterAndValue[] parameterValues) GetMethodAndParameterValues(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(null, null); } // Configure services if supported var serviceProvider = CreateServiceProvider(obj); 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, serviceProvider); ValidateVerbInput(method, parameterValues.Select(kvp => kvp.Value).ToList()); // if some args weren't handled // if (inputArgs.Any()) { throw new UnhandledParametersException(inputArgs); } return(method, parameterValues); }
internal static ParameterAndValue[] CreateParameterValues( Method method, object target, Dictionary <string, string> inputArgs, IEnumerable <Parameter> list) { var parameters = new List <ParameterAndValue>(); // inputArgs is getting emptied. // create a copy for the VerbExecutionContext // var inputArgsCopy = inputArgs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); foreach (var p in list) { var parameterInfo = p.ParameterInfo; var names = p.Names; // according to the parameter names, try to find a match from the input // var inputKey = names.FirstOrDefault(n => inputArgs.ContainsKey(n)); // the input value // string stringValue = null; // the actual value, converted to the relevant parameter type // object value = null; // if no input was found that matches this parameter // if (inputKey == null) { if (p.Required) { throw new MissingRequiredArgumentException(method, parameterInfo.Name); } if (p.DefaultProvider != null) { value = p.DefaultProvider.GetDefault(new VerbExecutionContext(method, target, inputArgsCopy)); } else { // the default is the value // value = p.Default; } // convert the default value, if different from parameter's value (guid, for example) // if (value is string && !(parameterInfo.ParameterType == typeof(string))) { value = GetValueForParameter(parameterInfo, parameterInfo.ParameterType, "{DEFAULT}", (string)value); } } else { stringValue = inputArgs[inputKey]; // remove it so later we'll see which ones were not handled // inputArgs.Remove(inputKey); } if (value == null && inputKey != null) { value = GetValueForParameter(parameterInfo, parameterInfo.ParameterType, inputKey, stringValue); } // validate each parameter // if (value != null && parameterInfo.HasAttribute <ValidationAttribute>()) { var validators = parameterInfo.GetAttributes <ValidationAttribute>().Select(a => a.GetValidator()); // all validators must pass // foreach (var validator in validators) { validator.Validate(new ValueInfo(parameterInfo.Name, parameterInfo.ParameterType, value)); } } // we have a valid value - add it to the list of parameters // parameters.Add(new ParameterAndValue(p, value)); } return(parameters.ToArray()); }