|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Introduction:First things first: I wrote this article mainly because I’ve found a complete lack of comprehensive information on the subject. Sure there are projects out there that show you how to make a simple plug-in that lets you do something dumb like feed it two numbers, and then one plug-in may add the two numbers together and return the result, while the other plug-in may multiply them instead. This is where I began, and is not bad reading as a prep tutorial to this tutorial. It might not be a bad idea to understand those tutorials first. However, when I began to search for how to bring GUIs into the plug-ins, I was completely lost. My aim is to show you how to do this, and provide some clear explanations. This tutorial will not be a step by step guide to making the program, as if you have the tutorial, you should also have the source code for the Tutorial project. I feel it unnecessary to go through this all, so instead I will only be covering some explanations on the code that is tricky. Tutorial:Notice that we have a Solution with 6 different projects in it. The first project is the Plugin Application Tester thingy. I like to refer to it as the Host, since it is the application that your plug-ins will be plugging-in to. This of course is the heart and soul of the whole Plug-in get-up. The plug-ins themselves are really not that complex as you will see. But before I go into the Host Application, let’s talk about the PluginInterface project. If you are unfamiliar with interfaces, please go find a tutorial and familiarize yourself with them. In a nutshell, they are ‘outlines’ of what properties and methods a Class that inherits a certain interface should have in them. There is very little code in this project. In fact, the only code we’re worried about is this:using System;
namespace PluginInterface
{
public interface IPlugin
{
IPluginHost Host {get;set;}
string Name {get;}
string Description {get;}
string Author {get;}
string Version {get;}
System.Windows.Forms.UserControl MainInterface {get;}
void Initialize();
void Dispose();
}
public interface IPluginHost
{
void Feedback(string Feedback, IPlugin Plugin);
}
}
In this code, we have 2 Next up, we have the Host project. This one is a bit more confusing. First of all, let’s get this cleared out of the way. I used a technique that may be a bit confusing at first for some, but once scaled up, can make things a bit simpler later on. using System;
namespace Host
{
/// <summary>
/// Holds A static instance of global program shtuff
/// </summary>
public class Global
{
public Global(){} //Constructor
//What have we done here?
public static Host.PluginServices Plugins = new PluginServices();
}
}
The above code is a trick I learned a little while ago. I have a class called The next bit of code I will introduce is the code that actually finds any compatible plug-in files in a certain folder, and adds them to a collection of 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);
}
}
}
This is a very simple method that accepts a path to look for plug-ins in. For example, you could tell it to look in your application’s Plugins folder. All it does is loop through all the files in the given directory, and check to see if the extension is of .dll type. Now you may be wondering if that’s enough to check for. What if someone renamed some random file as .dll and stuck it in? We’ll get to that later. You may have noticed in the last method, a call to another method //Create a new assembly from the plugin file we're adding..
Assembly pluginAssembly = Assembly.LoadFrom(FileName);
Next, we’re iterating through all the different types that the particular plug-in contains. It would be wise to note at this time, that you may want to put in some extra error catching around this area. I would imagine if you tried loading an //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);
}
This bit of code is the heart of the whole plug-in project. First, we declare a new So, we create a new instance of the plug-in with the following line: newPlugin.Instance = (IPlugin)
Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
After this is done, we can use the new instance of the plug-in, and set its The only other bit of code I think we should cover is the 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;
}
This is really simple actually. The whole idea of the OK, so we talked about the actual host application for the plug-ins, but we have yet to talk about the plug-ins themselves. The plug-ins themselves are not that complicated. All you have to do to make one is create a new Class Library project, and make a class that inherits the I’ll let you take a look at the actual plug-ins yourself. Plug-ins 1 through 3 are all made pretty much the same. They all have a Notice that in Plugin3, in the Finally, in Plugin4, we demonstrate that you don’t need to have a separate Conclusion:And that’s about it for plug-ins. Once you’ve grasped the concept of Interfaces, and have understood the code for actually initializing instances of plug-ins, creating an actual plug-in is not a very difficult task. I will leave you to explore the rest of the code by yourself. Hopefully you have learned something from this tutorial, and can successfully implement plug-ins into your own programs! HistoryFebruary 26th, 2004 - Submitted article.
| ||||||||||||||||||||