Просмотр исходного кода

Switched to MEF as a means to locate plugins and resolvers

LukePulverenti Luke Pulverenti luke pulverenti 13 лет назад
Родитель
Сommit
97ee9fed14
32 измененных файлов с 181 добавлено и 281 удалено
  1. 1 1
      MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs
  2. 1 1
      MediaBrowser.Api/HttpHandlers/PluginsHandler.cs
  3. 1 1
      MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs
  4. 1 0
      MediaBrowser.Api/MediaBrowser.Api.csproj
  5. 2 0
      MediaBrowser.Api/Plugin.cs
  6. 0 37
      MediaBrowser.Common/Configuration/ConfigurationController.cs
  7. 90 19
      MediaBrowser.Common/Kernel/BaseKernel.cs
  8. 1 2
      MediaBrowser.Common/MediaBrowser.Common.csproj
  9. 16 2
      MediaBrowser.Common/Plugins/BasePlugin.cs
  10. 0 130
      MediaBrowser.Common/Plugins/PluginController.cs
  11. 1 0
      MediaBrowser.Configuration/MediaBrowser.Configuration.csproj
  12. 3 1
      MediaBrowser.Configuration/Plugin.cs
  13. 0 24
      MediaBrowser.Controller/Configuration/ServerConfigurationController.cs
  14. 26 22
      MediaBrowser.Controller/Kernel.cs
  15. 1 13
      MediaBrowser.Controller/Library/ItemController.cs
  16. 1 1
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  17. 3 1
      MediaBrowser.Controller/Resolvers/AudioResolver.cs
  18. 3 4
      MediaBrowser.Controller/Resolvers/FolderResolver.cs
  19. 2 0
      MediaBrowser.Controller/Resolvers/VideoResolver.cs
  20. 1 0
      MediaBrowser.HtmlBrowser/MediaBrowser.HtmlBrowser.csproj
  21. 3 1
      MediaBrowser.HtmlBrowser/Plugin.cs
  22. 1 0
      MediaBrowser.InternetProviders/MediaBrowser.InternetProviders.csproj
  23. 3 1
      MediaBrowser.InternetProviders/Plugin.cs
  24. 1 0
      MediaBrowser.Movies/MediaBrowser.Movies.csproj
  25. 3 10
      MediaBrowser.Movies/Plugin.cs
  26. 2 0
      MediaBrowser.Movies/Resolvers/BoxSetResolver.cs
  27. 2 0
      MediaBrowser.Movies/Resolvers/MovieResolver.cs
  28. 1 0
      MediaBrowser.TV/MediaBrowser.TV.csproj
  29. 2 5
      MediaBrowser.TV/Plugin.cs
  30. 3 1
      MediaBrowser.TV/Resolvers/EpisodeResolver.cs
  31. 3 3
      MediaBrowser.TV/Resolvers/SeasonResolver.cs
  32. 3 1
      MediaBrowser.TV/Resolvers/SeriesResolver.cs

+ 1 - 1
MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs

@@ -12,7 +12,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
             {
                 string pluginName = QueryString["name"];
                 string pluginName = QueryString["name"];
 
 
-                return Kernel.Instance.PluginController.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
+                return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
             }
             }
         }
         }
     }
     }

+ 1 - 1
MediaBrowser.Api/HttpHandlers/PluginsHandler.cs

@@ -13,7 +13,7 @@ namespace MediaBrowser.Api.HttpHandlers
         {
         {
             get
             get
             {
             {
-                var plugins = Kernel.Instance.PluginController.Plugins.Select(p =>
+                var plugins = Kernel.Instance.Plugins.Select(p =>
                 {
                 {
                     return new PluginInfo()
                     return new PluginInfo()
                     {
                     {

+ 1 - 1
MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs

@@ -11,7 +11,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
             {
                 Guid userId = Guid.Parse(QueryString["userid"]);
                 Guid userId = Guid.Parse(QueryString["userid"]);
 
 
-                return Kernel.Instance.ConfigurationController.GetUserConfiguration(userId);
+                return Kernel.Instance.GetUserConfiguration(userId);
             }
             }
         }
         }
     }
     }

+ 1 - 0
MediaBrowser.Api/MediaBrowser.Api.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

+ 2 - 0
MediaBrowser.Api/Plugin.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.ComponentModel.Composition;
 using System.Reactive.Linq;
 using System.Reactive.Linq;
 using MediaBrowser.Api.HttpHandlers;
 using MediaBrowser.Api.HttpHandlers;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
@@ -9,6 +10,7 @@ using MediaBrowser.Model.Plugins;
 
 
 namespace MediaBrowser.Api
 namespace MediaBrowser.Api
 {
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
     {
         public override string Name
         public override string Name

+ 0 - 37
MediaBrowser.Common/Configuration/ConfigurationController.cs

@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.IO;
-using MediaBrowser.Common.Json;
-
-namespace MediaBrowser.Common.Configuration
-{
-    public class ConfigurationController<TConfigurationType>
-        where TConfigurationType : BaseConfiguration, new ()
-    {
-        /// <summary>
-        /// The path to the configuration file
-        /// </summary>
-        public string Path { get; set; }
-
-        public TConfigurationType Configuration { get; set; }
-
-        public void Reload()
-        {
-            if (!File.Exists(Path))
-            {
-                Configuration = new TConfigurationType();
-            }
-            else
-            {
-                Configuration = JsonSerializer.DeserializeFromFile<TConfigurationType>(Path);
-            }
-        }
-
-        public void Save()
-        {
-        }
-    }
-}

+ 90 - 19
MediaBrowser.Common/Kernel/BaseKernel.cs

@@ -1,6 +1,11 @@
-using System.Configuration;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.ComponentModel.Composition.Hosting;
+using System.Configuration;
 using System.IO;
 using System.IO;
+using System.Linq;
 using System.Reflection;
 using System.Reflection;
+using System.Threading.Tasks;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Common.Logging;
 using MediaBrowser.Common.Logging;
@@ -12,8 +17,7 @@ namespace MediaBrowser.Common.Kernel
     /// <summary>
     /// <summary>
     /// Represents a shared base kernel for both the UI and server apps
     /// Represents a shared base kernel for both the UI and server apps
     /// </summary>
     /// </summary>
-    public abstract class BaseKernel<TConfigurationContorllerType, TConfigurationType>
-        where TConfigurationContorllerType : ConfigurationController<TConfigurationType>, new()
+    public abstract class BaseKernel<TConfigurationType>
         where TConfigurationType : BaseConfiguration, new()
         where TConfigurationType : BaseConfiguration, new()
     {
     {
         /// <summary>
         /// <summary>
@@ -21,19 +25,39 @@ namespace MediaBrowser.Common.Kernel
         /// </summary>
         /// </summary>
         public string ProgramDataPath { get; private set; }
         public string ProgramDataPath { get; private set; }
 
 
+        protected string PluginsPath
+        {
+            get
+            {
+                return Path.Combine(ProgramDataPath, "plugins");
+            }
+        }
+
+        protected string ConfigurationPath
+        {
+            get
+            {
+                return Path.Combine(ProgramDataPath, "config.js");
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the current configuration
         /// Gets the current configuration
         /// </summary>
         /// </summary>
-        public TConfigurationContorllerType ConfigurationController { get; private set; }
+        public TConfigurationType Configuration { get; private set; }
 
 
+        /// <summary>
+        /// Gets the list of currently loaded plugins
+        /// </summary>
+        [ImportMany(typeof(BasePlugin))]
+        public IEnumerable<BasePlugin> Plugins { get; private set; }
+        
         /// <summary>
         /// <summary>
         /// Both the UI and server will have a built-in HttpServer.
         /// 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.
         /// People will inevitably want remote control apps so it's needed in the UI too.
         /// </summary>
         /// </summary>
         public HttpServer HttpServer { get; private set; }
         public HttpServer HttpServer { get; private set; }
 
 
-        public PluginController PluginController { get; private set; }
-
         /// <summary>
         /// <summary>
         /// Gets the kernel context. The UI kernel will have to override this.
         /// Gets the kernel context. The UI kernel will have to override this.
         /// </summary>
         /// </summary>
@@ -43,9 +67,6 @@ namespace MediaBrowser.Common.Kernel
         {
         {
             ProgramDataPath = GetProgramDataPath();
             ProgramDataPath = GetProgramDataPath();
 
 
-            PluginController = new PluginController() { PluginsPath = Path.Combine(ProgramDataPath, "Plugins") };
-            ConfigurationController = new TConfigurationContorllerType() { Path = Path.Combine(ProgramDataPath, "config.js") };
-
             Logger.LoggerInstance = new FileLogger(Path.Combine(ProgramDataPath, "Logs"));
             Logger.LoggerInstance = new FileLogger(Path.Combine(ProgramDataPath, "Logs"));
         }
         }
 
 
@@ -55,7 +76,51 @@ namespace MediaBrowser.Common.Kernel
 
 
             ReloadHttpServer();
             ReloadHttpServer();
 
 
-            ReloadPlugins();
+            ReloadComposableParts();
+        }
+
+        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);
+
+            OnComposablePartsLoaded();
+        }
+
+        protected virtual void OnComposablePartsLoaded()
+        {
+            StartPlugins();
+        }
+
+        private void StartPlugins()
+        {
+            Parallel.For(0, Plugins.Count(), i =>
+            {
+                var plugin = Plugins.ElementAt(i);
+
+                plugin.ReloadConfiguration();
+
+                if (plugin.Enabled)
+                {
+                    if (KernelContext == KernelContext.Server)
+                    {
+                        plugin.InitInServer();
+                    }
+                    else
+                    {
+                        plugin.InitInUI();
+                    }
+                }
+            });
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -87,9 +152,21 @@ namespace MediaBrowser.Common.Kernel
         private void ReloadConfiguration()
         private void ReloadConfiguration()
         {
         {
             // Deserialize config
             // Deserialize config
-            ConfigurationController.Reload();
+            if (!File.Exists(ConfigurationPath))
+            {
+                Configuration = new TConfigurationType();
+            }
+            else
+            {
+                Configuration = JsonSerializer.DeserializeFromFile<TConfigurationType>(ConfigurationPath);
+            }
 
 
-            Logger.LoggerInstance.LogSeverity = ConfigurationController.Configuration.LogSeverity;
+            Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity;
+        }
+
+        public void SaveConfiguration()
+        {
+            JsonSerializer.SerializeToFile(Configuration, ConfigurationPath);
         }
         }
 
 
         private void ReloadHttpServer()
         private void ReloadHttpServer()
@@ -99,13 +176,7 @@ namespace MediaBrowser.Common.Kernel
                 HttpServer.Dispose();
                 HttpServer.Dispose();
             }
             }
 
 
-            HttpServer = new HttpServer("http://+:" + ConfigurationController.Configuration.HttpServerPortNumber + "/mediabrowser/");
-        }
-
-        protected virtual void ReloadPlugins()
-        {
-            // Find plugins
-            PluginController.Init(KernelContext);
+            HttpServer = new HttpServer("http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/");
         }
         }
 
 
         private static TConfigurationType GetConfiguration(string directory)
         private static TConfigurationType GetConfiguration(string directory)

+ 1 - 2
MediaBrowser.Common/MediaBrowser.Common.csproj

@@ -34,6 +34,7 @@
       <HintPath>..\packages\ServiceStack.Text.3.8.5\lib\net35\ServiceStack.Text.dll</HintPath>
       <HintPath>..\packages\ServiceStack.Text.3.8.5\lib\net35\ServiceStack.Text.dll</HintPath>
     </Reference>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Configuration" />
     <Reference Include="System.Configuration" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -48,7 +49,6 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Compile Include="Configuration\BaseConfiguration.cs" />
     <Compile Include="Configuration\BaseConfiguration.cs" />
-    <Compile Include="Configuration\ConfigurationController.cs" />
     <Compile Include="Events\GenericItemEventArgs.cs" />
     <Compile Include="Events\GenericItemEventArgs.cs" />
     <Compile Include="Json\JsonSerializer.cs" />
     <Compile Include="Json\JsonSerializer.cs" />
     <Compile Include="Kernel\BaseKernel.cs" />
     <Compile Include="Kernel\BaseKernel.cs" />
@@ -67,7 +67,6 @@
     <Compile Include="Logging\Logger.cs" />
     <Compile Include="Logging\Logger.cs" />
     <Compile Include="Logging\LogRow.cs" />
     <Compile Include="Logging\LogRow.cs" />
     <Compile Include="Plugins\BasePlugin.cs" />
     <Compile Include="Plugins\BasePlugin.cs" />
-    <Compile Include="Plugins\PluginController.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>

+ 16 - 2
MediaBrowser.Common/Plugins/BasePlugin.cs

@@ -43,8 +43,22 @@ namespace MediaBrowser.Common.Plugins
     public abstract class BasePlugin
     public abstract class BasePlugin
     {
     {
         public abstract string Name { get; }
         public abstract string Name { get; }
-        public string Path { get; set; }
-        public Version Version { get; set; }
+
+        public string Path
+        {
+            get
+            {
+                return System.IO.Path.GetDirectoryName(GetType().Assembly.Location);
+            }
+        }
+
+        public Version Version
+        {
+            get
+            {
+                return GetType().Assembly.GetName().Version;
+            }
+        }
 
 
         public BasePluginConfiguration Configuration { get; protected set; }
         public BasePluginConfiguration Configuration { get; protected set; }
 
 

+ 0 - 130
MediaBrowser.Common/Plugins/PluginController.cs

@@ -1,130 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Kernel;
-
-namespace MediaBrowser.Common.Plugins
-{
-    /// <summary>
-    /// Manages Plugins within the PluginsPath directory
-    /// </summary>
-    public class PluginController
-    {
-        public string PluginsPath { get; set; }
-
-        /// <summary>
-        /// Gets the list of currently loaded plugins
-        /// </summary>
-        public IEnumerable<BasePlugin> Plugins { get; private set; }
-        
-        /// <summary>
-        /// Initializes the controller
-        /// </summary>
-        public void Init(KernelContext context)
-        {
-            AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(CurrentDomain_AssemblyResolve);
-            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
-
-            Plugins = GetAllPlugins();
-
-            Parallel.For(0, Plugins.Count(), i =>
-            {
-                var plugin = Plugins.ElementAt(i);
-
-                plugin.ReloadConfiguration();
-
-                if (plugin.Enabled)
-                {
-                    if (context == KernelContext.Server)
-                    {
-                        plugin.InitInServer();
-                    }
-                    else
-                    {
-                        plugin.InitInUI();
-                    }
-                }
-            });
-        }
-
-        /// <summary>
-        /// Gets all plugins within PluginsPath
-        /// </summary>
-        /// <returns></returns>
-        private IEnumerable<BasePlugin> GetAllPlugins()
-        {
-            if (!Directory.Exists(PluginsPath))
-            {
-                Directory.CreateDirectory(PluginsPath);
-            }
-
-            List<BasePlugin> plugins = new List<BasePlugin>();
-
-            foreach (string folder in Directory.GetDirectories(PluginsPath, "*", SearchOption.TopDirectoryOnly))
-            {
-                BasePlugin plugin = GetPluginFromDirectory(folder);
-
-                plugin.Path = folder;
-
-                if (plugin != null)
-                {
-                    plugins.Add(plugin);
-                }
-            }
-
-            return plugins;
-        }
-
-        private BasePlugin GetPluginFromDirectory(string path)
-        {
-            string dll = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly).FirstOrDefault();
-
-            if (!string.IsNullOrEmpty(dll))
-            {
-                return GetPluginFromDll(dll);
-            }
-
-            return null;
-        }
-
-        private BasePlugin GetPluginFromDll(string path)
-        {
-            return GetPluginFromDll(Assembly.Load(File.ReadAllBytes(path)));
-        }
-
-        private BasePlugin GetPluginFromDll(Assembly assembly)
-        {
-            var plugin = assembly.GetTypes().Where(type => typeof(BasePlugin).IsAssignableFrom(type)).FirstOrDefault();
-
-            if (plugin != null)
-            {
-                BasePlugin instance = plugin.GetConstructor(Type.EmptyTypes).Invoke(null) as BasePlugin;
-
-                instance.Version = assembly.GetName().Version;
-
-                return instance;
-            }
-
-            return null;
-        }
-
-        Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
-        {
-            AssemblyName assemblyName = new AssemblyName(args.Name);
-
-            IEnumerable<string> dllPaths = Directory.GetFiles(PluginsPath, "*.dll", SearchOption.AllDirectories);
-
-            string dll = dllPaths.FirstOrDefault(f => Path.GetFileNameWithoutExtension(f) == assemblyName.Name);
-
-            if (!string.IsNullOrEmpty(dll))
-            {
-                return Assembly.Load(File.ReadAllBytes(dll));
-            }
-
-            return null;
-        }
-    }
-}

+ 1 - 0
MediaBrowser.Configuration/MediaBrowser.Configuration.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <SpecificVersion>False</SpecificVersion>

+ 3 - 1
MediaBrowser.Configuration/Plugin.cs

@@ -1,8 +1,10 @@
-using MediaBrowser.Common.Plugins;
+using System.ComponentModel.Composition;
+using MediaBrowser.Common.Plugins;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;
 
 
 namespace MediaBrowser.Configuration
 namespace MediaBrowser.Configuration
 {
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
     {
         public override string Name
         public override string Name

+ 0 - 24
MediaBrowser.Controller/Configuration/ServerConfigurationController.cs

@@ -1,24 +0,0 @@
-using System;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Configuration;
-
-namespace MediaBrowser.Controller.Configuration
-{
-    /// <summary>
-    /// Extends BaseConfigurationController by adding methods to get and set UIConfiguration data
-    /// </summary>
-    public class ServerConfigurationController : ConfigurationController<ServerConfiguration>
-    {
-        private string GetDictionaryKey(Guid userId, string deviceName)
-        {
-            string guidString = userId == Guid.Empty ? string.Empty : userId.ToString();
-
-            return deviceName + "-" + guidString;
-        }
-
-        public UserConfiguration GetUserConfiguration(Guid userId)
-        {
-            return Configuration.DefaultUserConfiguration;
-        }
-    }
-}

+ 26 - 22
MediaBrowser.Controller/Kernel.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Security.Cryptography;
 using System.Security.Cryptography;
@@ -17,7 +18,7 @@ using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Controller
 namespace MediaBrowser.Controller
 {
 {
-    public class Kernel : BaseKernel<ServerConfigurationController, ServerConfiguration>
+    public class Kernel : BaseKernel<ServerConfiguration>
     {
     {
         public static Kernel Instance { get; private set; }
         public static Kernel Instance { get; private set; }
 
 
@@ -37,6 +38,12 @@ namespace MediaBrowser.Controller
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Gets the list of currently registered entity resolvers
+        /// </summary>
+        [ImportMany(typeof(IBaseItemResolver))]
+        public IEnumerable<IBaseItemResolver> EntityResolvers { get; private set; }
+        
         /// <summary>
         /// <summary>
         /// Creates a kernal based on a Data path, which is akin to our current programdata path
         /// Creates a kernal based on a Data path, which is akin to our current programdata path
         /// </summary>
         /// </summary>
@@ -51,35 +58,27 @@ namespace MediaBrowser.Controller
 
 
             ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath;
             ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath;
             ItemController.BeginResolvePath += ItemController_BeginResolvePath;
             ItemController.BeginResolvePath += ItemController_BeginResolvePath;
-
-            // Add support for core media types - audio, video, etc
-            AddBaseItemType<Folder, FolderResolver>();
-            AddBaseItemType<Audio, AudioResolver>();
-            AddBaseItemType<Video, VideoResolver>();
         }
         }
 
 
-        /// <summary>
-        /// Tells the kernel to start spinning up
-        /// </summary>
-        public override void Init()
+        protected override void OnComposablePartsLoaded()
         {
         {
-            base.Init();
+            List<IBaseItemResolver> resolvers = EntityResolvers.ToList();
+
+            // Add the internal resolvers
+            resolvers.Add(new VideoResolver());
+            resolvers.Add(new AudioResolver());
+            resolvers.Add(new FolderResolver());
+
+            EntityResolvers = resolvers;
+
+            // The base class will fire up all the plugins
+            base.OnComposablePartsLoaded();
 
 
             // Get users from users folder
             // Get users from users folder
             // Load root media folder
             // Load root media folder
             Parallel.Invoke(ReloadUsers, ReloadRoot);
             Parallel.Invoke(ReloadUsers, ReloadRoot);
         }
         }
 
 
-        /// <summary>
-        /// Registers a new BaseItem subclass
-        /// </summary>
-        public void AddBaseItemType<TBaseItemType, TResolverType>()
-            where TBaseItemType : BaseItem, new()
-            where TResolverType : BaseItemResolver<TBaseItemType>, new()
-        {
-            ItemController.AddResovler<TBaseItemType, TResolverType>();
-        }
-
         /// <summary>
         /// <summary>
         /// Fires when a path is about to be resolved, but before child folders and files 
         /// Fires when a path is about to be resolved, but before child folders and files 
         /// have been collected from the file system.
         /// have been collected from the file system.
@@ -147,6 +146,11 @@ namespace MediaBrowser.Controller
             }
             }
         }
         }
 
 
+        public UserConfiguration GetUserConfiguration(Guid userId)
+        {
+            return Configuration.DefaultUserConfiguration;
+        }
+        
         public void ReloadItem(BaseItem item)
         public void ReloadItem(BaseItem item)
         {
         {
             Folder folder = item as Folder;
             Folder folder = item as Folder;
@@ -250,7 +254,7 @@ namespace MediaBrowser.Controller
         {
         {
             DateTime now = DateTime.Now;
             DateTime now = DateTime.Now;
 
 
-            UserConfiguration config = ConfigurationController.GetUserConfiguration(userId);
+            UserConfiguration config = GetUserConfiguration(userId);
 
 
             return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < config.RecentItemDays);
             return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < config.RecentItemDays);
         }
         }

+ 1 - 13
MediaBrowser.Controller/Library/ItemController.cs

@@ -13,18 +13,6 @@ namespace MediaBrowser.Controller.Library
 {
 {
     public class ItemController
     public class ItemController
     {
     {
-        private List<IBaseItemResolver> Resolvers = new List<IBaseItemResolver>();
-
-        /// <summary>
-        /// Registers a new BaseItem resolver.
-        /// </summary>
-        public void AddResovler<TBaseItemType, TResolverType>()
-            where TBaseItemType : BaseItem, new()
-            where TResolverType : BaseItemResolver<TBaseItemType>, new()
-        {
-            Resolvers.Insert(0, new TResolverType());
-        }
-
         #region PreBeginResolvePath Event
         #region PreBeginResolvePath Event
         /// <summary>
         /// <summary>
         /// Fires when a path is about to be resolved, but before child folders and files 
         /// Fires when a path is about to be resolved, but before child folders and files 
@@ -127,7 +115,7 @@ namespace MediaBrowser.Controller.Library
         private BaseItem ResolveItem(ItemResolveEventArgs args)
         private BaseItem ResolveItem(ItemResolveEventArgs args)
         {
         {
             // If that didn't pan out, try the slow ones
             // If that didn't pan out, try the slow ones
-            foreach (IBaseItemResolver resolver in Resolvers)
+            foreach (IBaseItemResolver resolver in Kernel.Instance.EntityResolvers)
             {
             {
                 var item = resolver.ResolvePath(args);
                 var item = resolver.ResolvePath(args);
 
 

+ 1 - 1
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive">
     <Reference Include="System.Reactive">
       <HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
       <HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
@@ -43,7 +44,6 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Compile Include="Configuration\ServerConfiguration.cs" />
     <Compile Include="Configuration\ServerConfiguration.cs" />
-    <Compile Include="Configuration\ServerConfigurationController.cs" />
     <Compile Include="Events\ItemResolveEventArgs.cs" />
     <Compile Include="Events\ItemResolveEventArgs.cs" />
     <Compile Include="IO\DirectoryWatchers.cs" />
     <Compile Include="IO\DirectoryWatchers.cs" />
     <Compile Include="IO\Shortcut.cs" />
     <Compile Include="IO\Shortcut.cs" />

+ 3 - 1
MediaBrowser.Controller/Resolvers/AudioResolver.cs

@@ -1,9 +1,11 @@
-using System.IO;
+using System.ComponentModel.Composition;
+using System.IO;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 
 
 namespace MediaBrowser.Controller.Resolvers
 namespace MediaBrowser.Controller.Resolvers
 {
 {
+    [Export(typeof(IBaseItemResolver))]
     public class AudioResolver : BaseItemResolver<Audio>
     public class AudioResolver : BaseItemResolver<Audio>
     {
     {
         protected override Audio Resolve(ItemResolveEventArgs args)
         protected override Audio Resolve(ItemResolveEventArgs args)

+ 3 - 4
MediaBrowser.Controller/Resolvers/FolderResolver.cs

@@ -1,12 +1,11 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
+using System.ComponentModel.Composition;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
-using MediaBrowser.Model.Entities;
 using MediaBrowser.Controller.Xml;
 using MediaBrowser.Controller.Xml;
+using MediaBrowser.Model.Entities;
 
 
 namespace MediaBrowser.Controller.Resolvers
 namespace MediaBrowser.Controller.Resolvers
 {
 {
+    [Export(typeof(IBaseItemResolver))]
     public class FolderResolver : BaseFolderResolver<Folder>
     public class FolderResolver : BaseFolderResolver<Folder>
     {
     {
         protected override Folder Resolve(ItemResolveEventArgs args)
         protected override Folder Resolve(ItemResolveEventArgs args)

+ 2 - 0
MediaBrowser.Controller/Resolvers/VideoResolver.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
@@ -8,6 +9,7 @@ namespace MediaBrowser.Controller.Resolvers
     /// <summary>
     /// <summary>
     /// Resolves a Path into a Video
     /// Resolves a Path into a Video
     /// </summary>
     /// </summary>
+    [Export(typeof(IBaseItemResolver))]
     public class VideoResolver : BaseVideoResolver<Video>
     public class VideoResolver : BaseVideoResolver<Video>
     {
     {
     }
     }

+ 1 - 0
MediaBrowser.HtmlBrowser/MediaBrowser.HtmlBrowser.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive">
     <Reference Include="System.Reactive">
       <HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
       <HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>

+ 3 - 1
MediaBrowser.HtmlBrowser/Plugin.cs

@@ -1,9 +1,11 @@
-using MediaBrowser.Common.Plugins;
+using System.ComponentModel.Composition;
+using MediaBrowser.Common.Plugins;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;
 
 
 namespace MediaBrowser.HtmlBrowser
 namespace MediaBrowser.HtmlBrowser
 {
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
     {
         public override string Name
         public override string Name

+ 1 - 0
MediaBrowser.InternetProviders/MediaBrowser.InternetProviders.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="System.Data.DataSetExtensions" />

+ 3 - 1
MediaBrowser.InternetProviders/Plugin.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Common.Plugins;
+using System.ComponentModel.Composition;
+using MediaBrowser.Common.Plugins;
 
 
 namespace MediaBrowser.InternetProviders
 namespace MediaBrowser.InternetProviders
 {
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<PluginConfiguration>
     public class Plugin : BaseGenericPlugin<PluginConfiguration>
     {
     {
         public override string Name
         public override string Name

+ 1 - 0
MediaBrowser.Movies/MediaBrowser.Movies.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Xml.Linq" />

+ 3 - 10
MediaBrowser.Movies/Plugin.cs

@@ -1,22 +1,15 @@
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Controller;
+using System.ComponentModel.Composition;
+using MediaBrowser.Common.Plugins;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;
-using MediaBrowser.Movies.Entities;
-using MediaBrowser.Movies.Resolvers;
 
 
 namespace MediaBrowser.Movies
 namespace MediaBrowser.Movies
 {
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
     {
         public override string Name
         public override string Name
         {
         {
             get { return "Movies"; }
             get { return "Movies"; }
         }
         }
-
-        public override void InitInServer()
-        {
-            Kernel.Instance.AddBaseItemType<BoxSet, BoxSetResolver>();
-            Kernel.Instance.AddBaseItemType<Movie, MovieResolver>();
-        }
     }
     }
 }
 }

+ 2 - 0
MediaBrowser.Movies/Resolvers/BoxSetResolver.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Controller.Resolvers;
@@ -6,6 +7,7 @@ using MediaBrowser.Movies.Entities;
 
 
 namespace MediaBrowser.Movies.Resolvers
 namespace MediaBrowser.Movies.Resolvers
 {
 {
+    [Export(typeof(IBaseItemResolver))]
     public class BoxSetResolver : BaseFolderResolver<BoxSet>
     public class BoxSetResolver : BaseFolderResolver<BoxSet>
     {
     {
         protected override BoxSet Resolve(ItemResolveEventArgs args)
         protected override BoxSet Resolve(ItemResolveEventArgs args)

+ 2 - 0
MediaBrowser.Movies/Resolvers/MovieResolver.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
@@ -11,6 +12,7 @@ using MediaBrowser.Movies.Metadata;
 
 
 namespace MediaBrowser.Movies.Resolvers
 namespace MediaBrowser.Movies.Resolvers
 {
 {
+    [Export(typeof(IBaseItemResolver))]
     public class MovieResolver : BaseVideoResolver<Movie>
     public class MovieResolver : BaseVideoResolver<Movie>
     {
     {
         protected override Movie Resolve(ItemResolveEventArgs args)
         protected override Movie Resolve(ItemResolveEventArgs args)

+ 1 - 0
MediaBrowser.TV/MediaBrowser.TV.csproj

@@ -31,6 +31,7 @@
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Xml.Linq" />

+ 2 - 5
MediaBrowser.TV/Plugin.cs

@@ -1,13 +1,14 @@
 using System;
 using System;
+using System.ComponentModel.Composition;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.TV.Entities;
 using MediaBrowser.TV.Entities;
-using MediaBrowser.TV.Resolvers;
 
 
 namespace MediaBrowser.TV
 namespace MediaBrowser.TV
 {
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
     {
         public override string Name
         public override string Name
@@ -17,10 +18,6 @@ namespace MediaBrowser.TV
 
 
         public override void InitInServer()
         public override void InitInServer()
         {
         {
-            Kernel.Instance.AddBaseItemType<Series, SeriesResolver>();
-            Kernel.Instance.AddBaseItemType<Season, SeasonResolver>();
-            Kernel.Instance.AddBaseItemType<Episode, EpisodeResolver>();
-
             Kernel.Instance.ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath;
             Kernel.Instance.ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath;
         }
         }
 
 

+ 3 - 1
MediaBrowser.TV/Resolvers/EpisodeResolver.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
@@ -8,7 +9,8 @@ using MediaBrowser.TV.Metadata;
 
 
 namespace MediaBrowser.TV.Resolvers
 namespace MediaBrowser.TV.Resolvers
 {
 {
-    class EpisodeResolver : BaseVideoResolver<Episode>
+    [Export(typeof(IBaseItemResolver))]
+    public class EpisodeResolver : BaseVideoResolver<Episode>
     {
     {
         protected override Episode Resolve(ItemResolveEventArgs args)
         protected override Episode Resolve(ItemResolveEventArgs args)
         {
         {

+ 3 - 3
MediaBrowser.TV/Resolvers/SeasonResolver.cs

@@ -1,13 +1,13 @@
-using System;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
-using System.Linq;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.TV.Entities;
 using MediaBrowser.TV.Entities;
 
 
 namespace MediaBrowser.TV.Resolvers
 namespace MediaBrowser.TV.Resolvers
 {
 {
-    class SeasonResolver : BaseFolderResolver<Season>
+    [Export(typeof(IBaseItemResolver))]
+    public class SeasonResolver : BaseFolderResolver<Season>
     {
     {
         protected override Season Resolve(ItemResolveEventArgs args)
         protected override Season Resolve(ItemResolveEventArgs args)
         {
         {

+ 3 - 1
MediaBrowser.TV/Resolvers/SeriesResolver.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.IO;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Controller.Resolvers;
@@ -7,7 +8,8 @@ using MediaBrowser.TV.Metadata;
 
 
 namespace MediaBrowser.TV.Resolvers
 namespace MediaBrowser.TV.Resolvers
 {
 {
-    class SeriesResolver : BaseFolderResolver<Series>
+    [Export(typeof(IBaseItemResolver))]
+    public class SeriesResolver : BaseFolderResolver<Series>
     {
     {
         protected override Series Resolve(ItemResolveEventArgs args)
         protected override Series Resolve(ItemResolveEventArgs args)
         {
         {