Exemple #1
0
        /// <summary>
        /// Creates a new session
        /// </summary>
        /// <returns>The ID of the new session</returns>
        protected string BeginSession()
        {
            lock (SessionCollectionInternalLock)
            {
                // Initializes a new session
                var newSession = new SessionInfo();

                while (SessionCollectionInternal.ContainsKey(newSession.ID))
                {
                    // Keep pulling new sessions until it does not exists on the collection
                    newSession = new SessionInfo();
                }

                // Add the new session
                SessionCollectionInternal.Add(newSession.ID, newSession);

                // Returns the new session ID
                return(newSession.ID);
            }
        }
Exemple #2
0
        /// <summary>
        /// Finishes a given session by destroying all objects inside it
        /// </summary>
        /// <param name="sessionID">The ID Session</param>
        protected void EndSession(string sessionID)
        {
            lock (SessionCollectionInternalLock)
            {
                // Fetch Session
                if (SessionCollectionInternal.TryGetValue(sessionID, out var sessionInfo))
                {
                    // Loop thru objects and call dispose, if applicable
                    foreach (var kvp in sessionInfo.ObjectCollection)
                    {
                        if (kvp.Value is IDisposable disposable)
                        {
                            disposable.Dispose();
                        }
                    }

                    // Remove session from collection
                    SessionCollectionInternal.Remove(sessionID);
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Executes a command asynchronously
        /// </summary>
        /// <param name="sessionID">The ID of the session running the command</param>
        /// <param name="inputCommand">The full command input</param>
        /// <returns>A <see cref="CommandExecutionResponse"/> containing the results of the execution</returns>
        protected async Task <CommandExecutionResponse> ExecuteCommandAsync(string sessionID, string inputCommand)
        {
            try
            {
                // Notify CommandReceived event
                CommandReceived?.Invoke(this, new CommandReceivedEventArgs(inputCommand, sessionID));

                // Parse Full Command, by separating what is the command from what are the arguments
                var ResultingCommand = this.CommandParser.Parse(inputCommand);

                // Try to assign each parameter
                var methodArgumentsList = new List <object>();

                // If arguments are not specified, set an empty array to it
                if (ResultingCommand.Arguments == null)
                {
                    ResultingCommand.Arguments = new ParsedCommandArgument[] { }
                }
                ;

                // Look for command
                if (CommandCollectionInternal.TryGetValue(ResultingCommand.Command, out var commandInfo))
                {
                    // Check for Help Call
                    if (ResultingCommand.IsHelpRequest)
                    {
                        // Display the command help
                        var commandHelpAttribute = commandInfo.GetCommandHelpAttribute();
                        if (commandHelpAttribute == null)
                        {
                            return(CommandExecutionResponse.Help(""));
                        }

                        return(CommandExecutionResponse.Help(commandHelpAttribute.Contents));
                    }
                    else
                    {
                        // Check if required parameters have been informed, if they were not, display help (if available)

                        // Assign Parameters
                        if (ResultingCommand.IsArgumentParameterSpecific)
                        {
                            // The arguments have a parameter name or a identifier, set them in sequence to be used later
                            var currentArgumentsDictionary = new Dictionary <string, ParsedCommandArgument>();
                            foreach (var r in ResultingCommand.Arguments)
                            {
                                if (currentArgumentsDictionary.ContainsKey(r.Parameter.ToLower()))
                                {
                                    throw new Exception($"Parameter '{r.Parameter.ToLower()}' is repeated on the syntax");
                                }

                                currentArgumentsDictionary.Add(r.Parameter.ToLower(), r);
                            }

                            var newArgumentsList = new List <ParsedCommandArgument>();

                            foreach (var p in commandInfo.ParametersInfo)
                            {
                                if (currentArgumentsDictionary.TryGetValue(p.Name.ToLower(), out var parsedCommandArgument))
                                {
                                    throw new Exception($"Parameter '{p.Name.ToLower()}' is not informed");
                                }

                                newArgumentsList.Add(parsedCommandArgument);
                            }

                            ResultingCommand.Arguments = newArgumentsList.ToArray();
                        }

                        // Make sure the number of arguments match the method argument number
                        if (ResultingCommand.Arguments.Length == commandInfo.ParametersInfo.Length)
                        {
                            for (int iArgument = 0; iArgument < ResultingCommand.Arguments.Length; iArgument++)
                            {
                                // Get Variables
                                var param    = commandInfo.ParametersInfo[iArgument];
                                var argument = ResultingCommand.Arguments[iArgument];

                                // Try to apply parameter
                                try
                                {
                                    if (param.ParameterType == typeof(string))
                                    {
                                        // A direct conversion is available
                                        methodArgumentsList.Add(argument.Value);
                                    }
                                    else
                                    {
                                        // There is no direct conversion, try to apply the parameter using the Convert object
                                        methodArgumentsList.Add(Convert.ChangeType(argument, param.ParameterType));
                                    }
                                }
                                catch (Exception eAssignment)
                                {
                                    // Throw an error with the invalid argument
                                    throw new InvalidCommandArgumentsException(ResultingCommand.Command, param.Name, param.ParameterType, argument.Value, eAssignment);
                                }
                            }
                        }
                        else
                        {
                            // Number of arguments do not match, return help
                            var argumentException = new ArgumentException("The number of arguments needed for the command does not match the number of arguments provided");

                            var commandHelpAttribute = commandInfo.GetCommandHelpAttribute();
                            if (commandHelpAttribute == null)
                            {
                                return(CommandExecutionResponse.Help("", DefaultErrorStatus, argumentException));
                            }

                            return(CommandExecutionResponse.Help(commandHelpAttribute.Contents, DefaultErrorStatus, argumentException));
                        }

                        // Arguments are set

                        // Define the CommandClass where the command will be executed against
                        var commandObject = (object)null;

                        // Look for Session Information to start fetching / creating objects
                        if (SessionCollectionInternal.TryGetValue(sessionID, out SessionInfo sessionInfo))
                        {
                            // Session information found

                            // Retrieve command class info
                            if (CommandClassCollectionInternal.TryGetValue(commandInfo.CommandClassType, out var commandClassInfo))
                            {
                                // Check the CommandClass lifetime before trying to find the object where to run the command against
                                if (commandClassInfo.CommandClassAttribute.Lifetime == InstanceLifetimes.Singleton)
                                {
                                    // Singleton lifetime, only one instance of the object should exist

                                    // Make sure to lock the dictionary to force other threads to hold
                                    lock (SingletonObjectsCollectionInternalLock)
                                    {
                                        // Singleton - Object should be on the SingletonObjectCollectionInternal
                                        if (!(SingletonObjectsCollectionInternal.TryGetValue(commandInfo.CommandClassType, out commandObject)))
                                        {
                                            // Singleton object could not be found, then create it and add back to the collection

                                            // Create the Command Object
                                            commandObject = commandClassInfo.CreateInstance();

                                            // Adds the singleton object to the collection
                                            SingletonObjectsCollectionInternal.Add(commandInfo.CommandClassType, commandObject);
                                        }
                                    }
                                }
                                else if (commandClassInfo.CommandClassAttribute.Lifetime == InstanceLifetimes.Scoped)
                                {
                                    // Scoped lifetime, only one instance per session should exist

                                    // Check object on the Session Info
                                    if (!sessionInfo.ObjectCollection.TryGetValue(commandInfo.CommandClassType, out commandObject))
                                    {
                                        // Create and add object to the session
                                        lock (SessionCollectionInternalLock)
                                        {
                                            // Create the Command Object and add to collection
                                            commandObject = commandClassInfo.CreateInstance();
                                            sessionInfo.ObjectCollection.Add(commandInfo.CommandClassType, commandObject);
                                        }
                                    }
                                }
                                else
                                {
                                    // Transient lifetime, initializes it everytime
                                    commandObject = commandClassInfo.CreateInstance();
                                }
                            }
                            else
                            {
                                // Cannot find registration details for command class
                                throw new Exception($"Unable to find registration details for type '{commandInfo.CommandClassType.Name}'");
                            }
                        }
                        else
                        {
                            // Error, unable to find the session
                            throw new Exception($"Session {sessionID} cannot be found");
                        }

                        try
                        {
                            // Calls the Command Asynchronously
                            var result = await Task.Factory.StartNew <object>(() =>
                            {
                                return(commandInfo.MethodInfo.Invoke(commandObject, methodArgumentsList.ToArray()));
                            }
                                                                              ).ConfigureAwait(false);

                            // Depending on the type of result, throw response
                            if (result is CommandExecutionResponse cr)
                            {
                                return(cr);
                            }
                            else
                            {
                                // Command executed without exceptions, create a Success Response with no data
                                return(CommandExecutionResponse.Success(DefaultSuccessStatus, result));
                            }
                        }
                        catch (Exception eExecution)
                        {
                            // Throws the execution exception ahead
                            throw new CommandInExecutionException(ResultingCommand.Command, methodArgumentsList.ToArray(), eExecution);
                        }
                    }
                }
                else
                {
                    // Command not found, throw exception
                    throw new CommandNotFoundException(ResultingCommand.Command);
                }
            }
            catch (InvalidCommandArgumentsException e)
            {
                return(CommandExecutionResponse.Error(DefaultErrorStatus, e));
            }
            catch (CommandNotFoundException)
            {
                return(CommandExecutionResponse.NotFound(DefaultNotFoundStatus));
            }
            catch (Exception e)
            {
                return(CommandExecutionResponse.Error(DefaultErrorStatus, e));
            }
        }