/// <summary>Invokes a command on an object by matching the command to a method using reflection.</summary> /// <typeparam name="TObject">The object type on which to search the method. This can be used to pass an interface or a base type.</typeparam> /// <param name="executor">The object on which to invoke the method.</param> /// <param name="argumentCollection">The command argument list.</param> /// <returns>The value returned by the invoked method.</returns> /// <exception cref="OvermindException">Thrown if the command could not be matched to an executor method.</exception> public object Invoke <TObject>(TObject executor, IList <string> argumentCollection) { const int argumentOffset = 2; // To ignore the executor and method names from the arguments if (argumentCollection.Count < 2) { throw new OvermindException("[CommandInterpreter] Invalid arguments: missing executor method name"); } int methodArgumentCount = argumentCollection.Count - argumentOffset; MethodInfo methodInfo = GetExecutorMethods(typeof(TObject)) .SingleOrDefault(method => method.Name.Equals(argumentCollection[1], StringComparison.InvariantCultureIgnoreCase) && methodArgumentCount <= method.GetParameters().Length && methodArgumentCount >= method.GetParameters().Count(p => p.IsOptional == false)); if (methodInfo == null) { throw new OvermindException("[CommandInterpreter] Invalid arguments: executor method not found"); } IList <ParameterInfo> parameters = methodInfo.GetParameters(); object[] parameterValues = new object[parameters.Count]; for (int parameterIndex = 0; parameterIndex < methodArgumentCount; parameterIndex++) { object value = null; Type parameterType = parameters[parameterIndex].ParameterType; string argument = argumentCollection[parameterIndex + argumentOffset]; if (parameterType == typeof(byte[])) { value = ByteExtensions.FromHexString(argument); } else if (parameterType.IsEnum) { value = Enum.Parse(parameterType, argument, true); } else { value = Convert.ChangeType(argument, parameterType); } parameterValues[parameterIndex] = value; } for (int parameterIndex = methodArgumentCount; parameterIndex < parameters.Count; parameterIndex++) { parameterValues[parameterIndex] = parameters[parameterIndex].DefaultValue; } return(methodInfo.Invoke(executor, parameterValues)); }