internal static async Task LoadPluginsAsync() { _appLogArea.WriteLine(""); List <string> dlls = Directory.EnumerateFiles("Plugins").Where(f => Path.GetExtension(f) == ".dll").ToList(); dlls.Insert(0, Assembly.GetExecutingAssembly().Location); foreach (string str in Config.AdditionalPluginDirectories) { dlls.AddRange(Directory.EnumerateFiles(str).Where(f => Path.GetExtension(f) == ".dll")); } _appLogArea.WriteLine($"{(Commands.Any() ? "Reloading" : "Loading")} {dlls.Count()} plugins..."); Commands.Clear(); AssemblyCommands.Clear(); ParseExtensions.Clear(); foreach (string dllPath in dlls) { try { Assembly assembly = Assembly.LoadFrom(dllPath); if (assembly != null && assembly.DefinedTypes.Any(t => t.GetInterfaces()?.Contains(typeof(ICommandsAssembly)) == true)) { Debug.WriteLine(dllPath); _appLogArea.WriteLine($"Searching {Path.GetFileName(dllPath)} for commands."); ICommandsAssembly asm = null; List <DiscordCommand> asmCommands = new List <DiscordCommand>(); foreach (Type type in assembly.GetTypes()) { if (type.GetInterfaces().Contains(typeof(ICommandsAssembly))) { asm = (ICommandsAssembly)Activator.CreateInstance(type); } if (type.GetInterfaces().Contains(typeof(IParseExtension))) { ParseExtensions.Add((IParseExtension)Activator.CreateInstance(type)); } if (type.GetInterfaces().Contains(typeof(IParamConverter))) { Tools.RegisterPatameterParseExtension((IParamConverter)Activator.CreateInstance(type)); } if (type.IsSubclassOf(typeof(DiscordCommand)) && !type.IsAbstract) { DiscordCommand command = InstantateDiscordCommand(type); if (command != null) { asmCommands.Add(command); } } } if (asm == null) { _appLogArea.WriteLine($"Loaded {asmCommands.Count()} commands from {Path.GetFileName(dllPath)} without command assembly manifest. Categorised help will be unavailable for these commands."); _appLogArea.WriteLine("Consider adding an \"ICommandAssembly\" class as soon as possible."); } else { if (asm is IBotStartup s) { await s.Startup(Client); } _appLogArea.WriteLine($"Loaded {asmCommands.Count()} plugins from {Path.GetFileName(dllPath)}!"); } Commands.AddRange(asmCommands); if (asm != null) { AssemblyCommands.Add(asm, asmCommands); } } } catch (Exception ex) { _appLogArea.WriteLine($"An {ex.GetType().Name} occured while loading from {Path.GetFileName(dllPath)}\n{ex.Message}"); } } _appLogArea.WriteLine(""); _appLogArea.WriteLine($"Plugins loaded!"); _appLogArea.WriteLine($"{Commands.Count} commands available: {string.Join(", ", Commands.Select(c => c.Name))}"); _appLogArea.WriteLine($"{ParseExtensions.Count} parse extensions available: {string.Join(", ", ParseExtensions.Select(c => c.Name))}"); _appLogArea.WriteLine(""); }