Trigger4Win/Trigger/Tasks/TaskManager.cs
2015-04-10 00:09:58 +00:00

186 lines
6.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows.Forms;
namespace Trigger.Tasks
{
/// <summary>
/// <para>This <see cref="Manager"/> takes care of all available <see cref="TaskPlugin"/>s and automatically loads them on startup</para>
/// </summary>
public class Manager
{
#region Properties
/// <summary><para>Our <see cref="Main"/> <see cref="Form"/></para></summary>
private Main Main;
/// <summary><para>A List of available <see cref="TaskPlugin"/>s</para></summary>
public List<Type> TaskPluginsAvailable;
/// <summary><para>A List of actually loaded (=active) <see cref="TaskPlugin"/>s</para></summary>
public List<Type> TaskPluginsLoaded = new List<Type>();
/// <summary><para>A List with the instances of the <see cref="TaskPlugin"/>s</para></summary>
private List<TaskPlugin> TaskPluginInstances = new List<TaskPlugin>();
/// <summary><para>A flag that indicates whether the loading process should be aborted</para></summary>
private bool abort = false;
#endregion
#region Constructors
/// <summary></summary>
/// <param name="Main"></param>
public Manager(Main Main)
{
this.Main = Main;
List<Type> types = this.getAvailableTasks();
this.TaskPluginsAvailable = types;
this.Refresh();
}
#endregion
#region Methods
/// <summary>
/// <para>Returns the current status of this <see cref="Manager"/></para>
/// <para>This includes the lists with available and with loaded <see cref="TaskPlugin"/>s</para>
/// </summary>
/// <returns></returns>
public TreeNode GetStatus(TreeView tv)
{
TreeNode tnMain = new TreeNode("Task Manager");
TreeNode tnAvailable = tnMain.Nodes.Add("Available Tasks (" + this.TaskPluginsAvailable.Count + ")");
this.TaskPluginsAvailable.ForEach(new Action<Type>((item) => tnAvailable.Nodes.Add(new TreeNode(item.Name))));
TreeNode tnLoaded = tnMain.Nodes.Add("Loaded Tasks (" + this.TaskPluginInstances.Count + ")");
this.TaskPluginInstances.ForEach(new Action<TaskPlugin>((tp) => tnLoaded.Nodes.Add(tp.GetStatus(tv))));
return tnMain;
}
/// <summary>
/// <para>Gets a list of all available <see cref="TaskPlugin"/>s using Reflection</para>
/// </summary>
/// <returns></returns>
private List<Type> getAvailableTasks()
{
List<Type> types = new List<Type>(System.Reflection.Assembly.GetExecutingAssembly().GetTypes());
types = types.FindAll(new Predicate<Type>(item => { return item.BaseType == typeof(TaskPlugin) && item.Namespace.StartsWith("Trigger.Tasks"); }));
return types;
}
/// <summary>
/// <para>Loads all <see cref="TaskPlugin"/>s that are not found or enabled in settings</para>
/// </summary>
private void Refresh()
{
ObservableDictionary<string, bool> plugins = TaskOptions.GetPluginsSetting();
List<Type> types = new List<Type>(this.TaskPluginsAvailable);
types = types.FindAll(new Predicate<Type>(item => { return !plugins.ContainsKey(item.Name) || plugins[item.Name]; }));
foreach (Type type in types)
{
if (abort)
break;
loadTask(type);
};
abort = false;
}
/// <summary>
/// <para>Loads all <see cref="TaskPlugin"/>s that are enabled in <paramref name="plugins"/> and not yet loaded and
/// unloads all <see cref="TaskPlugin"/>s that are disabled in <paramref name="plugins"/> and but still loaded</para>
/// <para>This method is used by <see cref="TaskOptions"/> to notify us about changes</para>
/// <param name="plugins">The list of plugins and whether they shall be enabled</param>
/// </summary>
public void Refresh(ObservableDictionary<string, bool> plugins)
{
foreach (KeyValuePair<string, bool> plugin in plugins)
{
if (abort)
break;
Type type = this.TaskPluginsLoaded.Find(new Predicate<Type>(item => { return item.Name == plugin.Key; }));
if (plugin.Value && type == null) // task is enabled and not loaded
this.loadTask(plugin.Key);
if (!plugin.Value && type != null)
this.unloadTask(type);
}
abort = false;
}
/// <summary>
/// <para>Creates an instance of the specified <paramref name="type"/></para>
/// </summary>
/// <param name="type"></param>
private void loadTask(string type)
{
this.loadTask(this.TaskPluginsAvailable.Find(new Predicate<Type>(item => { return item.Name == type; })));
}
/// <summary>
/// <para>Creates an instance of the specified <paramref name="type"/></para>
/// </summary>
/// <param name="type"></param>
private void loadTask(Type type)
{
try
{
#if DEBUG
System.Diagnostics.Stopwatch swInitEvent = new System.Diagnostics.Stopwatch();
swInitEvent.Start();
#endif
TaskPlugin task = (TaskPlugin)Activator.CreateInstance(type);
#if DEBUG
if (new List<System.Reflection.MethodInfo>(type.GetMethods()).Find(new Predicate<System.Reflection.MethodInfo>(m => { return m.Name == "Init" && m.GetParameters().Length == 2; })) != null)
task.Init(this.Main, swInitEvent);
else
task.Init(this.Main);
#else
if (task.Init(this.Main))
#endif
{
this.TaskPluginInstances.Add(task);
this.TaskPluginsLoaded.Add(type);
#if DEBUG
swInitEvent.Stop();
this.Main.Log.LogLine("Loaded Task plugin \"" + type.Name + "\" in " + swInitEvent.ElapsedMilliseconds + "ms", Log.Type.Other);
#else
this.Main.Log.LogLine("Loaded Task plugin \"" + type.Name + "\"", Log.Type.Other);
#endif
}
}
catch (Exception e)
{
MessageBox.Show(e.Message + "\n\n" + e.StackTrace, "Error when loading Task \"" + type.Name + "\"!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// <para>Destructs the instance of the specified <paramref name="type"/></para>
/// </summary>
/// <param name="type"></param>
private void unloadTask(Type type)
{
try
{
TaskPlugin task = this.TaskPluginInstances.Find(new Predicate<TaskPlugin>(item => { return item.GetType() == type; }));
task.Dispose();
this.TaskPluginInstances.Remove(task);
this.TaskPluginsLoaded.Remove(type);
this.Main.Log.LogLine("Unloaded Task plugin \"" + type.Name + "\"", Log.Type.Other);
}
catch (Exception e)
{
MessageBox.Show(e.Message + "\n\n" + e.StackTrace, "Error when unloading Task \"" + type.Name + "\"!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
internal void Abort()
{
this.abort = true;
}
#endregion
}
}