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 { /// /// Manages Plugins within the PluginsPath directory /// public class PluginController { public string PluginsPath { get; set; } /// /// Gets the list of currently loaded plugins /// public IEnumerable Plugins { get; private set; } /// /// Initializes the controller /// 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 => { Plugins.ElementAt(i).Init(); }); } /// /// Gets all plugins within PluginsPath /// /// private IEnumerable GetAllPlugins() { if (!Directory.Exists(PluginsPath)) { Directory.CreateDirectory(PluginsPath); } List plugins = new List(); foreach (string folder in Directory.GetDirectories(PluginsPath, "*", SearchOption.TopDirectoryOnly)) { IPlugin plugin = GetPluginFromDirectory(folder); plugin.Path = folder; if (plugin != null) { plugins.Add(plugin); } } return plugins; } private IPlugin GetPluginFromDirectory(string path) { string dll = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly).FirstOrDefault(); if (!string.IsNullOrEmpty(dll)) { return GetPluginFromDll(dll); } return null; } private IPlugin GetPluginFromDll(string path) { return GetPluginFromDll(Assembly.Load(File.ReadAllBytes(path))); } private IPlugin GetPluginFromDll(Assembly assembly) { var plugin = assembly.GetTypes().Where(type => typeof(IPlugin).IsAssignableFrom(type)).FirstOrDefault(); if (plugin != null) { return plugin.GetConstructor(Type.EmptyTypes).Invoke(null) as IPlugin; } return null; } Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { AssemblyName assemblyName = new AssemblyName(args.Name); IEnumerable 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; } } }