Tag Archives: Plugin Manager

Even more on the generic plugin manager

I’ve written previously about writing your own generic plugin manager/framework.

I believe that this is a worthwhile exercise for the beginning programmer, because it firstly teaches you a lot about reflection, and secondly teaches you the advantages that proper use of interfaces can bring to your code. Thirdly it can also teach you to think about how your API might be used by someone else when they write a plugin for your program. In short I think it’s a great exercise.

While writing and using my own plugin framework has been a great learning experience for me, I’ve found that I have outgrown it’s usefulness to me. What made me see this was when I started to think about and begin implementing a way for me to use the framework as a IoC/Dependency Injection tool. This led me off on some Googling and I found Funq, and the the associated screencasts by Cazzulino.

This got me to thinking about DRY. Don’t Repeat Yourself can just as easily mean Don’t Repeat Work Other People Have Already Done (If You Don’t Have To), but DRWOPHADIYDHT doesn’t sound/look nice as an acronym. Perhaps a better way to express that sentiment is “lazyDRY”, or “The re-use of prexisting libraries and code can save you a lot of time, and which effort you can put into your application at a higher level.”

Or in other words, it is foolish to ignore the work that other people have done, unless you have a compelling reason to do so. If you really want to write your own IoC/DI container, then great, knock yourself out. No one is going to stop you.

I’m lazy though. Nanos gigantium humeris insidentes.

Depending on the blogs in your feed reader, or who you follow on Twitter, or just in general googling, you will probably come across references to the same group of IoC/DI containers. Chiefly:

There are others, but it would seem hardly anyone uses them. Of those above, I have so far only used StructureMap and Ninject, and have really liked using both of them. I will try out the others at some point, but so far I’ve liked what I’ve seen in StructureMap and Ninject, I honestly don’t think that any of the others will have anything better to offer me. Besides which, StructureMap has a built in method of using it as a plugin framework. Win.

In Conclusion

What can I draw from all this? I don’t think that I wasted any of my time or effort in writing my own plugin framework. It was a worthwhile exercise which taught me a lot of things, and I urge you to do the same.

More on the generic plugin manager

Update:

I’ve written some more about what I’ve learned whilst working on my plugin manager here: http://temporalcohesion.co.uk/2010/03/17/even-more-on-the-generic-plugin-manager/

A few months ago I wrote about writing a generic plugin loader/manager in C#, where I offered links to several articles and referenced a rather excellent book about C# which I had used to base my plugin loader on. I hadn’t really given it much thought since then, but according to Google Analytic’s, it’s one of the most hit posts on my blog. Recently I had a request to release the source code.

Now when I first wrote that post, I was hesitant to include any code, and I still am – not because I think there is something new and unique with what I’ve done – but, rather that what I have written is not terribly difficult to write. I do not mean to sound snobbish or arrogant at all, I’m just telling you how it is, all I’ve done is to do a bit of reflection on assemblies in a folder, and load instances of certain interfaces.

Anyway…

The scenario is that you want to provide a way for for 3rd parties to be able to add additional functionality to your application at run time. We need to provide a common way for 3rd parties to be able to register their new functionality into our application, in order that the user can take advantage of the exciting new feature being added to the application.

Straight away, you should be thinking to yourself: Interface!

[csharp]

public interface IPlugin
{
/// <summary>
/// Does what ever It is.
/// </summary>
void Do(Action it);
}

[/csharp]

Anyone who now wants to create a plugin for our application must implement our IPlugin interface, as it defines the contract to which our application is bound to, in order to recognise and load plugins. Thus any assembly, that has a class which implements IPlugin is considered by our application to be a plugin which is capable of offering additional functionality.

We can now attempt to load our plugins. We need to have a class which can scan a folder for assemblies, scan those assemblies for types which implement IPlugin, and then create instances of them which our application can use. Loading the assemblies is easy:

[csharp]
public class PluginLoader<T>
{
private IList<T> pluginsList = new List<T>();

}

public virtual IList<T> LoadPlugins()
{
foreach (string file in Directory.GetFiles(this.pluginFolderPath, "*.dll", SearchOption.AllDirectories))
{
Assembly assembly = Assembly.LoadFile(file);
this.LoadObjects(assembly);
}

return this.pluginsList;
}
[/csharp]

We create a generic class, so we can use it with any type of plugin, and not just ones which implement IPlugin, then it’s just simple directory recursion to load all the files in the specified folder which have a file extension of .dll. The real magic happens in the LoadObjects() method.

[csharp]
var types = from t in assembly.GetTypes()
where t.IsClass &&
(t.GetInterface(typeof(T).Name) != null)
select t;

foreach (Type t in types)
{
T plugin = (T)assembly.CreateInstance(t.FullName, true);
this.pluginsList.Add(plugin);
}
[/csharp]

Using LINQ, we extract all the types from the assembly which are classes, which implement the interface which is a typeof(T) – T being the type we specified when we instantiated the class. You could just as easily here specify the type should inherit from some other type, and you could also check to see if a class has some assembly level attribute.

Why would you want to do that? Well, we can use an assembly level attribute to decorate the plugin class with meta-data about the plugin, such as the author, a short description, the name of the plugin, and it’s version.

[csharp]
public virtual KeyValuePair<string, List<KeyValuePair<string, string>>> GetPluginInformation(Type type)
{
var attributeInfo = from pa in type.GetCustomAttributes(false)
where (pa.GetType() == typeof(PluginAttribute))
select pa;

foreach (PluginAttribute p in attributeInfo)
{
data.Add(new KeyValuePair<string, string>("Author", p.Author));
data.Add(new KeyValuePair<string, string>("Description", p.Description));
data.Add(new KeyValuePair<string, string>("Name", p.Name));
name = p.Name;
data.Add(new KeyValuePair<string, string>("Type", p.Type.ToString()));
data.Add(new KeyValuePair<string, string>("Version", p.Version));
}

this.attributeInformation = new KeyValuePair<string, List<KeyValuePair<string, string>>>(name, data);

return this.attributeInformation;
}
[/csharp]

Or you could create a struct to use as a DTO for the plugin meta-data, it’s up to you.

I’ve removed all the comments and exception handling from the code I’ve posted purely just to save space, you’d really want to include that – especially the exception handling. But that’s really all there is to it, you might want to have a property to access the actual plugin list, or return it from a LoadPlugins method, it’s up to you.

You’ll notice I’ve made the methods virtual, you may want to use this class as a base class in another class. For instance I’ve got an additional class which inherits from my plugin loader class which does specific tasks for a particular type of plugin, and another which does different tasks for a different type of plugin.

Writing a generic plugin manager in C#

Update:

I have written another post on this subject with some code examples here: http://temporalcohesion.co.uk/2009/11/02/more-on-the-generic-plugin-manager/

Update 2:

There is another follow on post here: http://temporalcohesion.co.uk/2010/03/17/even-more-on-the-generic-plugin-manager/ where I talk about what I’ve learned.

One of my current long term hobby project is a map/world editor that I’m writing for Andy’s (work in progress) game engine. It is still in a quite rudimentary stage, however, I have gotten an important aspect of the application into a fairly mature state already, and that is the plugin system.

I don’t want to get into too much detail over things that are available via some simple searches on google, so don’t expect too much code. There are some good articles here, here and here, which delve quite deeply into this, and how to develop a plugin framework in general. I developed my plugin framework based on the code in this book, which incidentally is a very good book.

Also, in my own google searches on this subject, a lot of the articles I found are getting to be four years old, in a few instances even older. Not that this automatically makes them invalid as sources of information, it’s just that they may not reflect best practices in modern C#. (Not that I am claiming to be a Jon Skeet-like C# guru). Also, quite a few of the ones I found make use of an XML configuration file to hold a reference to the plugins. I’m not a big fan of this type of thing, I much prefer convention over configuration.

Why Generic?

I’ve written a plugin system for the Editor because I want to provide a way to make it easily extendible in the future, without having to change the core application, to enable it to perform actions that are above and beyond it’s core capabilities. Byond that basic requirement, there are a couple of other reasons to make it a generic plugin framework.

Firstly, I’ve made it generic because I wanted to make a distinction between different types of plugins, such as a type of plugin for resources, and a type of plugin which adds functionality into the application (such as tools, UI widgets etc).

Secondly, and perhaps most important (to me, anyway), is that I’ll never need to write a C# plugin framework again, for any of my personal projects. I’ve had a go at writing a plugin framework before, a few times for none-work projects and once for a project at work, and I finally realised what my problem was – reinventing the wheel each time.

The plugin framework I’ve written ensures that I don’t have to worry about this the next time one of my pet projects needs a plugin system. The Editor will in fact have two types of plugins available, one to extend the types of data sources it can load in resources from, and another to provide additional functionality, like tools.

I’m fairly pleased with the way that it has turned out, and it works quite well in practice.