public Task AddCommandModuleAsync <T>() where T : new() { var type = typeof(T); CommandsList.AddRange(type.GetMethods().Where(x => x.HasAttribute <CommandAttribute>() && x.IsPublic).Select(x => new Command() { ClassInstance = new T(), Method = x, MethodParams = x.GetParameters(), CommandName = x.GetCustomAttribute <CommandAttribute>().CommandName, Aliases = x.GetCustomAttribute <AliasesAttribute>()?.Aliases, ParentCommandName = null } as Command?)); var groups = typeof(T).GetNestedTypes().Where(x => x.IsPublic && (x.HasAttribute <GroupAttribute>())) as IReadOnlyList <Type>; for (var count = 0; count < groups?.Count(); count++) { var submths = groups[count].GetMethods().Where(x => x.IsPublic && (x.GetCustomAttribute <CommandAttribute>() != null)) as IReadOnlyList <MethodInfo>; var subcmds = new List <Command>(); for (var i = 0; i < submths.Count(); i++) { subcmds.Add(new Command() { ClassInstance = groups[count], Method = CommandsList[i].Value.Method, Aliases = CommandsList[i].Value.Method.GetCustomAttribute <AliasesAttribute>()?.Aliases, CommandName = CommandsList[i].Value.Method.GetCustomAttribute <CommandAttribute>().CommandName, ParentCommandName = groups[count].GetCustomAttribute <GroupAttribute>().GroupName }); } GroupCommandsList.Add(new CommandGroup() { GroupName = groups[count].GetCustomAttribute <GroupAttribute>().GroupName, Aliases = groups[count].GetCustomAttribute <AliasesAttribute>().Aliases, SubCommands = subcmds, ExecuteMethod = subcmds.FirstOrDefault(x => x.Method.Name == "ExecuteGroupAsync").Method }); } return(Task.CompletedTask); }