public void LoadAll() { BeforeLoad(); // Plugins are stored in format {PluginDir}/{PluginName}/AthamePlugin.*.dll var subDirs = Directory.GetDirectories(PluginDirectory); foreach (var dir in subDirs) { var name = Path.GetFileName(dir); try { // Attempt to load a .pdb if one exists var basePath = Path.Combine(dir, PluginDllPrefix + name); var dllFilename = basePath + ".dll"; var pdbFilename = basePath + ".pdb"; var theAssembly = File.Exists(pdbFilename) ? Assembly.Load(File.ReadAllBytes(dllFilename), File.ReadAllBytes(pdbFilename)) : Assembly.Load(File.ReadAllBytes(dllFilename)); // Set basic information about the assembly var plugin = new PluginInstance { Assembly = theAssembly, AssemblyDirectory = dir, Name = name }; Plugins.Add(plugin); Activate(plugin); AreAnyLoaded = true; } catch (Exception ex) { Log.WriteException(Level.Error, Tag, ex, $"While loading plugin {name}"); var eventArgs = new PluginLoadExceptionEventArgs { PluginName = name, Exception = ex, Continue = true }; LoadException?.Invoke(this, eventArgs); if (!eventArgs.Continue) { return; } } } }
private void Activate(PluginInstance instance) { Log.Debug(Tag, $"Attempting to load {instance.Name}"); if (IsAlreadyLoaded(instance.Assembly.GetName())) { return; } // Check that it references some form of the Plugin API assembly AssemblyName pluginApiName; if ( (pluginApiName = instance.Assembly.GetReferencedAssemblies() .FirstOrDefault(name => name.Name == PluginApiAssemblyName.Name)) != null) { if (pluginApiName.Version.Major != PluginApiAssemblyName.Version.Major) { throw new PluginIncompatibleException($"Wrong major version of Athame.PluginAPI referenced: expected {PluginApiAssemblyName}, found {pluginApiName}"); } } else { throw new PluginLoadException("Plugin does not reference Athame.PluginAPI.", instance.AssemblyDirectory); } var types = instance.Assembly.GetExportedTypes(); // Only filter for types which can be instantiated and implement IPlugin somehow. var implementingType = types.FirstOrDefault( type => !type.IsInterface && !type.IsAbstract && type.GetInterface(nameof(IPlugin)) != null); if (implementingType == null) { throw new PluginLoadException("No exported types found implementing IPlugin.", instance.AssemblyDirectory); } // Activate base plugin var plugin = (IPlugin)Activator.CreateInstance(implementingType); if (plugin.ApiVersion != ApiVersion) { throw new PluginIncompatibleException($"Plugin declares incompatible API version: expected {ApiVersion}, found {plugin.ApiVersion}."); } instance.Info = plugin.Info; instance.Plugin = plugin; var servicePlugin = plugin as MusicService; var context = new PluginContext { PluginDirectory = instance.AssemblyDirectory }; instance.Context = context; if (servicePlugin != null) { var settingsPath = Path.Combine(SettingsDirectory, String.Format(SettingsFileFormat, plugin.Info.Name)); var settingsFile = new SettingsFile(settingsPath, servicePlugin.Settings.GetType(), servicePlugin.Settings); instance.SettingsFile = settingsFile; } else { throw new PluginLoadException("IPlugin type does not implement MusicService.", instance.AssemblyDirectory); } }