using System; using System.IO; using System.Reflection; using PluginInterface; namespace IntelliDispatch { /// /// Summary description for PluginServices. /// public class PluginServices : IPluginHost //<--- Notice how it inherits IPluginHost interface! { /// /// Constructor of the Class /// public PluginServices() { } private Types.AvailablePlugins colAvailablePlugins = new Types.AvailablePlugins(); /// /// A Collection of all Plugins Found and Loaded by the FindPlugins() Method /// public Types.AvailablePlugins AvailablePlugins { get {return colAvailablePlugins;} set {colAvailablePlugins = value;} } /// /// Searches the Application's Startup Directory for Plugins /// public void FindPlugins() { FindPlugins(AppDomain.CurrentDomain.BaseDirectory); } /// /// Searches the passed Path for Plugins /// /// Directory to search for Plugins in public void FindPlugins(string Path) { //First empty the collection, we're reloading them all colAvailablePlugins.Clear(); //Go through all the files in the plugin directory foreach (string fileOn in Directory.GetFiles(Path)) { FileInfo file = new FileInfo(fileOn); //Preliminary check, must be .dll if (file.Extension.Equals(".dll")) { //Add the 'plugin' this.AddPlugin(fileOn); } } } /// /// Unloads and Closes all AvailablePlugins /// public void ClosePlugins() { foreach (Types.AvailablePlugin pluginOn in colAvailablePlugins) { //Close all plugin instances //We call the plugins Dispose sub first incase it has to do //Its own cleanup stuff pluginOn.Instance.Dispose(); //After we give the plugin a chance to tidy up, get rid of it pluginOn.Instance = null; } //Finally, clear our collection of available plugins colAvailablePlugins.Clear(); } private void AddPlugin(string FileName) { //Create a new assembly from the plugin file we're adding.. Assembly pluginAssembly = Assembly.LoadFrom(FileName); //Next we'll loop through all the Types found in the assembly foreach (Type pluginType in pluginAssembly.GetTypes()) { if (pluginType.IsPublic) //Only look at public types { if (!pluginType.IsAbstract) //Only look at non-abstract types { //Gets a type object of the interface we need the plugins to match Type typeInterface = pluginType.GetInterface("PluginInterface.IPlugin", true); //Make sure the interface we want to use actually exists if (typeInterface != null) { //Create a new available plugin since the type implements the IPlugin interface Types.AvailablePlugin newPlugin = new Types.AvailablePlugin(); //Set the filename where we found it newPlugin.AssemblyPath = FileName; //Create a new instance and store the instance in the collection for later use //We could change this later on to not load an instance.. we have 2 options //1- Make one instance, and use it whenever we need it.. it's always there //2- Don't make an instance, and instead make an instance whenever we use it, then close it //For now we'll just make an instance of all the plugins newPlugin.Instance = (IPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); //Set the Plugin's host to this class which inherited IPluginHost newPlugin.Instance.Host = this; //Call the initialization sub of the plugin newPlugin.Instance.Initialize(); //Add the new plugin to our collection here this.colAvailablePlugins.Add(newPlugin); //cleanup a bit newPlugin = null; } typeInterface = null; //Mr. Clean } } } pluginAssembly = null; //more cleanup } /// /// Displays a feedback dialog from the plugin /// /// String message for feedback /// The plugin that called the feedback public void Feedback(string Feedback, IPlugin Plugin) { //This sub makes a new feedback form and fills it out //With the appropriate information //This method can be called from the actual plugin with its Host Property System.Windows.Forms.Form newForm = null; frmFeedback newFeedbackForm = new frmFeedback(); //Here we set the frmFeedback's properties that i made custom newFeedbackForm.PluginAuthor = "By: " + Plugin.Author; newFeedbackForm.PluginDesc = Plugin.Description; newFeedbackForm.PluginName = Plugin.Name; newFeedbackForm.PluginVersion = Plugin.Version; newFeedbackForm.Feedback = Feedback; //We also made a Form object to hold the frmFeedback instance //If we were to declare if not as frmFeedback object at first, //We wouldn't have access to the properties we need on it newForm = newFeedbackForm; newForm.ShowDialog(); newFeedbackForm = null; newForm = null; } } namespace Types { /// /// Collection for AvailablePlugin Type /// public class AvailablePlugins : System.Collections.CollectionBase { //A Simple Home-brew class to hold some info about our Available Plugins /// /// Add a Plugin to the collection of Available plugins /// /// The Plugin to Add public void Add(Types.AvailablePlugin pluginToAdd) { this.List.Add(pluginToAdd); } /// /// Remove a Plugin to the collection of Available plugins /// /// The Plugin to Remove public void Remove(Types.AvailablePlugin pluginToRemove) { this.List.Remove(pluginToRemove); } /// /// Finds a plugin in the available Plugins /// /// The name or File path of the plugin to find /// Available Plugin, or null if the plugin is not found public Types.AvailablePlugin Find(string pluginNameOrPath) { Types.AvailablePlugin toReturn = null; //Loop through all the plugins foreach (Types.AvailablePlugin pluginOn in this.List) { //Find the one with the matching name or filename if ((pluginOn.Instance.Name.Equals(pluginNameOrPath)) || pluginOn.AssemblyPath.Equals(pluginNameOrPath)) { toReturn = pluginOn; break; } } return toReturn; } } /// /// Data Class for Available Plugin. Holds and instance of the loaded Plugin, as well as the Plugin's Assembly Path /// public class AvailablePlugin { //This is the actual AvailablePlugin object.. //Holds an instance of the plugin to access //ALso holds assembly path... not really necessary private IPlugin myInstance = null; private string myAssemblyPath = ""; public IPlugin Instance { get {return myInstance;} set {myInstance = value;} } public string AssemblyPath { get {return myAssemblyPath;} set {myAssemblyPath = value;} } } } }