Plugin Interfaces in .NET

Having a plugin system implemented into your applications allows users and other developers to enhance the functionality of your application. This tutorial will guide you through the creation of this kind of system.

The type of system we will be designing will load DLL plugins dynamically during runtime, meaning that to install a plugin, you'd just drop the DLL into the application folder and the application would load the plugin when it's running. This article assumes basic knowledge of .NET as well as requires at least .NET 2.0 to be installed. All source code and binaries are available for download.

IPlugin
To implement this system, we will use a IPlugin interface to explain how our plugins will look in code. This is extremely customizable and you can put whatever you want into your interface, but in this case, we'll just manage the name of the plugin, as well as the author:

public interface IPlugin
{
string Name { get; }
string Author { get; }
}

Sample Plugin
Now to create a plugin, all we have to do is make a new project, add reference to our main application, and then do something like this:

public class SamplePlugin : PluginInterface.IPlugin
{
public string Name
{
get { return "Sample Plugin"; }
}
public string Author
{
get { return "Rob Loach"; }
}
}

Plugin Manager
Seeing that we have a plugin and our interface, we'll have to create a Plugin Manager that will control loading all of our plugins at runtime. This will go in the main application:

public class PluginManager : List
{
public PluginManager(string pluginsPath)
{
Add(pluginsPath);
}
public PluginManager() : this(".")
{
}
public void Add(string pluginsPath)
{
foreach (FileInfo file in new DirectoryInfo(pluginsPath).GetFiles())
{
Assembly asm;
try
{
asm = Assembly.LoadFile(file.FullName);
}
catch
{
continue;
}
foreach (Type type in asm.GetTypes())
foreach (Type interf in type.GetInterfaces())
if (interf == typeof(IPlugin))
this.Add((IPlugin)Activator.CreateInstance(type));
}
}
}

As you can see, this PluginManager will maintain a list of IPlugins. When we create a PluginManager object, we pass in the plugins path where all the DLL plugins are kept. It then loads all the plugins in that path and stores them as objects in the list. So now that we have our plugin manager, we can use it:

PluginManager manager = new PluginManager();
Console.WriteLine("\nLoaded Plugins:");
foreach (IPlugin plugin in manager)
{
Console.WriteLine(" - " + plugin.Name + " by " + plugin.Author);
}

Since the default value when creating the PluginManager object is ".", it will load all plugins in the application path. If you passed in "plugins", it would load all plugins in the application's plugins sub-directory.

Conclusion
This system is very good for creating a plugin system. It allows end users to develop their own plugins for your application and extend its functionality. This kind of system could even be put to use to implement sub-systems of your application.

My challenge to you, now, is to develop your own plugin interface and put it to good use with sub-systems. If you use graphics in your application, implement a graphics sub-system for managing all graphics functionality. Make a sound plugin to manage all audio functionality. Make a networking plugin to manage all network code. With these systems in place, you'll allow end users to enhance the functionality of your program.