/// <summary> /// Loads all methods tagged with <see cref="CommandAttribute"/> from a given type, be they /// public or private. /// </summary> /// <param name="type">Type where to load commands from</param> /// <param name="instance">Instance to use when invoking the methods (null for static classes)</param> public void LoadCommands(Type type, object instance) { if (type is null) { throw new ArgumentNullException(nameof(type)); } // Find static/non-static methods (choose between static and instance by the presence of // a non-null instance) foreach (var method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .OrderBy(method => method.Name)) { if (method.IsDefined(typeof(CommandAttribute))) { // Create a single instance of the command (will validate and compile in the constructor) var command = new CompiledCommand(method, instance); CommandList.Add(command); // Get all command attributes and then register all of them with the same command foreach (var attr in method.GetCustomAttributes <CommandAttribute>()) { if (CommandLookupTable.ContainsKey(attr.Name) && !attr.Overwrite) { var existingCommand = (CompiledCommand)CommandLookupTable[attr.Name]; throw new CommandDefinitionException(method, $"Command name {attr.Name} is already defined in: {GetFullName(existingCommand.Method, existingCommand.Instance)}"); } CommandLookupTable[attr.Name] = command; } } } }
/// <summary> /// Registers a command to end the command loop with the provided names /// </summary> /// <param name="names">All possible names for the exit command</param> public void AddStopCommand(params string[] names) { if (names == null) { throw new ArgumentNullException(nameof(names)); } if (names.Length < 1) { throw new ArgumentException("No names provided.", nameof(names)); } var exitCommand = new CompiledCommand( typeof(ConsoleCommandManager).GetMethod(nameof(Stop)), this, names, "Exits this command loop."); CommandList.Add(exitCommand); foreach (var name in names) { CommandLookupTable[name] = exitCommand; } HasExitCommand = true; }