예제 #1
0
        private void Activate(PluginInstance instance)
        {
            Log.Debug(Tag, $"Attempting to load {instance.Name}");
            if (IsAlreadyLoaded(instance.Assembly.GetName()))
            {
                return;
            }

            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 PluginLoadException($"Plugin declares incompatible API version: expected {ApiVersion}, found {plugin.ApiVersion}.",
                                              instance.AssemblyDirectory);
            }
            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 = Program.DefaultApp.UserDataPathOf(Path.Combine(SettingsDir, 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);
            }
        }
예제 #2
0
        public void LoadAll()
        {
            BeforeLoad();

            // Plugins are stored in format {PluginDir}/{PluginName}/AthamePlugin.*.dll
            var subDirs = Directory.GetDirectories(PluginDirectory);

            isLoading = true;
            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;
                    }
                }
            }
            isLoading = false;
        }