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.Documents;
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);
}
}
}
}