Very simple plugin mechanism in C#

NET%20LogoOnce again I had to face the famous content aggregator problem. I already have done that on several project so I decided to write an article on that for the ones who wonders how to accomplish things like that.

Background

So, the situation is : I have a system, who consume several services, aggregate the results and provide the output to the user. I also want to be able to develop each providers class as separated assemblies (plugins) so the providers can develop their own plugins and distribute them to the software users without having to recompile the application, just by dragging the assembly within a folder. Here’s a diagram that resume the situation.

Plugin1

Technical Analysis

Regarding the requirements, some answers can seem obvious. First, we need to provide an interface to define what’s a plugin. Then, we need something to control the plugin creation and access. This component will also be responsible in this case for the plugin call. Each providers will have his own implementation of the IPlugin interface. In this case, the manager called PluginProvider, will be a singleton instance and instantiate the plugins on creation. Here’s the basic UML diagram of the system with some example providers.

Plugin2

Then, we have a dependency tree like this one

Plugin3

The assemblies that contains plugins will be placed in a folder where the application will look at startup. They just need to know the interface to implement and the data types exchanged if required. The UI layer refer the core, that contain the PluginManager and the shared assembly. No references to the plugins are created.

Implementation

The implementation is pretty simple. Here’s our plugin interface :

public interface IPlugin
{
    string Name { get; }
    void Action();
}

Then we can implement a basic plugin like this :

public sealed class ExternalPlugin : IPlugin
{
    public string Name
    {
        get { return "Exemple Plugin"; }
    }

    public void Action()
    {
        DoSomething();
    }
}

And finally, the most important thing, the PluginManager.

public sealed class PluginProvider
{
    private static PluginProvider instance;
    /// Warning ! Not a thread safe implementation, change it if needed
    public static PluginProvider Instance { get { return instance ?? (instance = new PluginProvider()); } }

    private List pluginInstances;

    private PluginProvider()
    {

    }

    public void Initialize()
    {
        pluginInstances = pluginInstances ??
               (from file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Plugin\"), "*.dll")
                from type in Assembly.LoadFrom(file).GetTypes()
                where type.GetInterfaces().Contains(typeof(IPlugin))
                select (IPlugin)Activator.CreateInstance(type)).ToList();
    }

    public void Action()
    {
        if(pluginInstances != null)
            pluginInstances.ForEach(plugin => plugin.Action());
    }
}

So, first we have a basic not thread safe singleton implementation. When we call the Initialize() method, the Linq query will list all the dll in the Plugin application folder, load each assemblies, find the types that implement IPlugin and then create an instance of them. All the instances are then stored in the pluginInstances private list. When we call PluginProvider.Instance.Action(), we iterate over each instance and call the Action() method. If the method return something, we can easily adapt the code to aggregate the call returns and return it to the PluginProvider caller. And that’s pretty much it !

Conclusion

This architecture can then be improved with for example repositories for query caching, using code contract to improve strength, using a thread safe singleton implementation, using a facade to directly call Providers.Action() or make this generic to be able to work with any interface which inherit from IPlugin… With all these improvements you’ll start to have a kind of little plugin framework in our personal toolbox. Modularity is usually a key factor in software development and that kind of pattern are really usefull for a lot of scenario.

If you have any questions, feel free to ask in the comments below 🙂

See you next time and keep it bug free !

Published by Emmanuel Istace

Musician, Software developer and guitar instructor. https://emmanuelistace.be/

4 thoughts on “Very simple plugin mechanism in C#

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: