diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 0edfeab25f..cd12c29804 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -1,11 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using System.Configuration; using System.IO; using System.Linq; using System.Reflection; -using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Json; using MediaBrowser.Common.Logging; @@ -25,6 +25,9 @@ namespace MediaBrowser.Common.Kernel /// public string ProgramDataPath { get; private set; } + /// + /// Gets the path to the plugin directory + /// protected string PluginsPath { get @@ -33,6 +36,9 @@ namespace MediaBrowser.Common.Kernel } } + /// + /// Gets the path to the application configuration file + /// protected string ConfigurationPath { get @@ -51,7 +57,7 @@ namespace MediaBrowser.Common.Kernel /// [ImportMany(typeof(BasePlugin))] public IEnumerable Plugins { get; private set; } - + /// /// Both the UI and server will have a built-in HttpServer. /// People will inevitably want remote control apps so it's needed in the UI too. @@ -79,34 +85,51 @@ namespace MediaBrowser.Common.Kernel ReloadComposableParts(); } + /// + /// Uses MEF to locate plugins + /// Subclasses can use this to locate types within plugins + /// protected void ReloadComposableParts() { if (!Directory.Exists(PluginsPath)) { Directory.CreateDirectory(PluginsPath); } - + var catalog = new AggregateCatalog(Directory.GetDirectories(PluginsPath, "*", SearchOption.TopDirectoryOnly).Select(f => new DirectoryCatalog(f))); //catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); //catalog.Catalogs.Add(new AssemblyCatalog(GetType().Assembly)); - new CompositionContainer(catalog).ComposeParts(this); + var container = new CompositionContainer(catalog); + + container.ComposeParts(this); OnComposablePartsLoaded(); + + catalog.Dispose(); + container.Dispose(); } + /// + /// Fires after MEF finishes finding composable parts within plugin assemblies + /// protected virtual void OnComposablePartsLoaded() { + // This event handler will allow any plugin to reference another + AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(CurrentDomain_AssemblyResolve); + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); + StartPlugins(); } + /// + /// Initializes all plugins + /// private void StartPlugins() { - Parallel.For(0, Plugins.Count(), i => + foreach (BasePlugin plugin in Plugins) { - var plugin = Plugins.ElementAt(i); - plugin.ReloadConfiguration(); if (plugin.Enabled) @@ -120,7 +143,7 @@ namespace MediaBrowser.Common.Kernel plugin.InitInUI(); } } - }); + } } /// @@ -149,6 +172,9 @@ namespace MediaBrowser.Common.Kernel return programDataPath; } + /// + /// Reloads application configuration from the config file + /// private void ReloadConfiguration() { // Deserialize config @@ -164,11 +190,17 @@ namespace MediaBrowser.Common.Kernel Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity; } + /// + /// Saves the current application configuration to the config file + /// public void SaveConfiguration() { JsonSerializer.SerializeToFile(Configuration, ConfigurationPath); } + /// + /// Restarts the Http Server, or starts it if not currently running + /// private void ReloadHttpServer() { if (HttpServer != null) @@ -179,16 +211,24 @@ namespace MediaBrowser.Common.Kernel HttpServer = new HttpServer("http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/"); } - private static TConfigurationType GetConfiguration(string directory) + /// + /// This snippet will allow any plugin to reference another + /// + Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { - string file = Path.Combine(directory, "config.js"); + AssemblyName assemblyName = new AssemblyName(args.Name); + + // Look for the .dll recursively within the plugins directory + string dll = Directory.GetFiles(PluginsPath, "*.dll", SearchOption.AllDirectories) + .FirstOrDefault(f => Path.GetFileNameWithoutExtension(f) == assemblyName.Name); - if (!File.Exists(file)) + // If we found a matching assembly, load it now + if (!string.IsNullOrEmpty(dll)) { - return new TConfigurationType(); + return Assembly.Load(File.ReadAllBytes(dll)); } - return JsonSerializer.DeserializeFromFile(file); + return null; } } } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 7cf12ff3f4..025add7c51 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.Controller EntityResolvers = resolvers; - // The base class will fire up all the plugins + // The base class will start up all the plugins base.OnComposablePartsLoaded(); // Get users from users folder diff --git a/MediaBrowser.InternetProviders/Plugin.cs b/MediaBrowser.InternetProviders/Plugin.cs index c9a6d1de87..bbf3ceaffb 100644 --- a/MediaBrowser.InternetProviders/Plugin.cs +++ b/MediaBrowser.InternetProviders/Plugin.cs @@ -10,9 +10,5 @@ namespace MediaBrowser.InternetProviders { get { return "Internet Providers"; } } - - public override void InitInServer() - { - } } }