Browse Source

Switched to MEF as a means to locate plugins and resolvers

LukePulverenti Luke Pulverenti luke pulverenti 13 năm trước cách đây
mục cha
commit
97ee9fed14
32 tập tin đã thay đổi với 181 bổ sung281 xóa
  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"];
 
-                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
             {
-                var plugins = Kernel.Instance.PluginController.Plugins.Select(p =>
+                var plugins = Kernel.Instance.Plugins.Select(p =>
                 {
                     return new PluginInfo()
                     {

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

@@ -11,7 +11,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
                 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>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <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.ComponentModel.Composition;
 using System.Reactive.Linq;
 using MediaBrowser.Api.HttpHandlers;
 using MediaBrowser.Common.Net;
@@ -9,6 +10,7 @@ using MediaBrowser.Model.Plugins;
 
 namespace MediaBrowser.Api
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
         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.Linq;
 using System.Reflection;
+using System.Threading.Tasks;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Json;
 using MediaBrowser.Common.Logging;
@@ -12,8 +17,7 @@ namespace MediaBrowser.Common.Kernel
     /// <summary>
     /// Represents a shared base kernel for both the UI and server apps
     /// </summary>
-    public abstract class BaseKernel<TConfigurationContorllerType, TConfigurationType>
-        where TConfigurationContorllerType : ConfigurationController<TConfigurationType>, new()
+    public abstract class BaseKernel<TConfigurationType>
         where TConfigurationType : BaseConfiguration, new()
     {
         /// <summary>
@@ -21,19 +25,39 @@ namespace MediaBrowser.Common.Kernel
         /// </summary>
         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>
         /// Gets the current configuration
         /// </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>
         /// 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.
         /// </summary>
         public HttpServer HttpServer { get; private set; }
 
-        public PluginController PluginController { get; private set; }
-
         /// <summary>
         /// Gets the kernel context. The UI kernel will have to override this.
         /// </summary>
@@ -43,9 +67,6 @@ namespace MediaBrowser.Common.Kernel
         {
             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"));
         }
 
@@ -55,7 +76,51 @@ namespace MediaBrowser.Common.Kernel
 
             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>
@@ -87,9 +152,21 @@ namespace MediaBrowser.Common.Kernel
         private void ReloadConfiguration()
         {
             // 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()
@@ -99,13 +176,7 @@ namespace MediaBrowser.Common.Kernel
                 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)

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

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

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

@@ -43,8 +43,22 @@ namespace MediaBrowser.Common.Plugins
     public abstract class BasePlugin
     {
         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; }
 

+ 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>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive, Version=1.0.10621.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <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;
 
 namespace MediaBrowser.Configuration
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
         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.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.Linq;
 using System.Security.Cryptography;
@@ -17,7 +18,7 @@ using MediaBrowser.Model.Users;
 
 namespace MediaBrowser.Controller
 {
-    public class Kernel : BaseKernel<ServerConfigurationController, ServerConfiguration>
+    public class Kernel : BaseKernel<ServerConfiguration>
     {
         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>
         /// Creates a kernal based on a Data path, which is akin to our current programdata path
         /// </summary>
@@ -51,35 +58,27 @@ namespace MediaBrowser.Controller
 
             ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath;
             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
             // Load root media folder
             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>
         /// Fires when a path is about to be resolved, but before child folders and files 
         /// 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)
         {
             Folder folder = item as Folder;
@@ -250,7 +254,7 @@ namespace MediaBrowser.Controller
         {
             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);
         }

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

@@ -13,18 +13,6 @@ namespace MediaBrowser.Controller.Library
 {
     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
         /// <summary>
         /// 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)
         {
             // 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);
 

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

@@ -31,6 +31,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive">
       <HintPath>..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll</HintPath>
@@ -43,7 +44,6 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Configuration\ServerConfiguration.cs" />
-    <Compile Include="Configuration\ServerConfigurationController.cs" />
     <Compile Include="Events\ItemResolveEventArgs.cs" />
     <Compile Include="IO\DirectoryWatchers.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.Model.Entities;
 
 namespace MediaBrowser.Controller.Resolvers
 {
+    [Export(typeof(IBaseItemResolver))]
     public class AudioResolver : BaseItemResolver<Audio>
     {
         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.Model.Entities;
 using MediaBrowser.Controller.Xml;
+using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Controller.Resolvers
 {
+    [Export(typeof(IBaseItemResolver))]
     public class FolderResolver : BaseFolderResolver<Folder>
     {
         protected override Folder Resolve(ItemResolveEventArgs args)

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

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

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

@@ -31,6 +31,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Reactive">
       <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.Model.Plugins;
 
 namespace MediaBrowser.HtmlBrowser
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
         public override string Name

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

@@ -31,6 +31,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Xml.Linq" />
     <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
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<PluginConfiguration>
     {
         public override string Name

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

@@ -31,6 +31,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Core" />
     <Reference Include="System.Runtime.Serialization" />
     <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.Movies.Entities;
-using MediaBrowser.Movies.Resolvers;
 
 namespace MediaBrowser.Movies
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
         public override string Name
         {
             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.ComponentModel.Composition;
 using System.IO;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Resolvers;
@@ -6,6 +7,7 @@ using MediaBrowser.Movies.Entities;
 
 namespace MediaBrowser.Movies.Resolvers
 {
+    [Export(typeof(IBaseItemResolver))]
     public class BoxSetResolver : BaseFolderResolver<BoxSet>
     {
         protected override BoxSet Resolve(ItemResolveEventArgs args)

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

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

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

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

+ 2 - 5
MediaBrowser.TV/Plugin.cs

@@ -1,13 +1,14 @@
 using System;
+using System.ComponentModel.Composition;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.TV.Entities;
-using MediaBrowser.TV.Resolvers;
 
 namespace MediaBrowser.TV
 {
+    [Export(typeof(BasePlugin))]
     public class Plugin : BaseGenericPlugin<BasePluginConfiguration>
     {
         public override string Name
@@ -17,10 +18,6 @@ namespace MediaBrowser.TV
 
         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;
         }
 

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

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

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

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