using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Text; using RainmeterStudio.Core; using RainmeterStudio.Core.Editor; using RainmeterStudio.Core.Utils; using RainmeterStudio.Resources; namespace RainmeterStudio.Business { /// /// Manages RainmeterStudio plugins /// public class PluginManager { #region Private fields List _loadedPlugins = new List(); Dictionary _registerExportTypes = new Dictionary(); #endregion /// /// Gets an enumerable of the loaded plugins /// public IEnumerable LoadedPlugins { get { return _loadedPlugins; } } /// /// A method which registers an object that was exported by a plugin. /// /// Object to register public delegate void RegisterExportHandler(object objectToRegister); #region Constructor /// /// Initializes the plugin manager /// public PluginManager() { } #endregion /// /// Adds a handler that registers exported objects of a specific type. /// /// The data type /// Handler that does the registring public void AddRegisterExportTypeHandler(Type interfaceType, RegisterExportHandler method) { _registerExportTypes.Add(interfaceType, method); } /// /// Initializes the plugin manager /// /// This will load all the plugins from the "StudioPlugins" folder public void Initialize() { // Initialize the executing assembly InitializePlugin(Assembly.GetExecutingAssembly()); // Load plugins from StudioPlugins folder var location = Assembly.GetExecutingAssembly().Location; var pluginsPath = Path.Combine(Path.GetDirectoryName(location), "StudioPlugins"); LoadPlugins(pluginsPath); } /// /// Loads all the plugins from the specified directory. /// /// Directory path public void LoadPlugins(string pluginsPath) { // Load all DLLs from "Plugins" folder foreach (var file in Directory.EnumerateFiles(pluginsPath, "*.dll")) LoadPlugin(file); } /// /// Tries to load the plugin. /// /// File name /// If plugin is not loaded, the function fails silently. public void LoadPlugin(string file) { Assembly assembly = null; // Try to load assembly try { assembly = Assembly.LoadFile(file); } catch (Exception ex) { Debug.WriteLine("Failed to load assembly {0}: {1}", file, ex); } // Loaded, do initialization stuff if (assembly != null) { // Check for the RainmeterStudioPlugin attribute if (assembly.GetCustomAttributes(typeof(RainmeterStudioPluginAttribute), false).Count() > 0) { _loadedPlugins.Add(assembly); InitializePlugin(assembly); Debug.WriteLine("Loaded plugin: {0}", (object)assembly.Location); } } } private void InitializePlugin(Assembly assembly) { // Register exports assembly.GetTypes() // Select only the classes .Where(type => type.IsClass) // That have the AutoRegister attribute .Where(type => type.GetCustomAttributes(typeof(PluginExportAttribute), false).Length > 0) // Perform register .ForEach((type) => { foreach (var pair in _registerExportTypes) { if (pair.Key.IsAssignableFrom(type)) { var constructor = type.GetConstructor(new Type[0]); var obj = constructor.Invoke(new object[0]); pair.Value(obj); } } }); // Register .resource files foreach (var resourceName in assembly.GetManifestResourceNames()) { var name = Path.GetFileNameWithoutExtension(resourceName); ResourceManager manager = new ResourceManager(name, assembly); ResourceProvider.RegisterManager(manager, assembly); } } } }