Creating plugins in C#: The Application (Part 4/4)

Welcome to the fourth and final part of our little tutorial ^.^

In this part I’ll explain how the application works and what you need in order for it to work…

The application

Alright, we have our handler and plugin. It’s time to load the plugin from within our application πŸ˜‰

Add a new C# Windows Form project called TestApplication (Add > New Project)

Add a reference to the PluginHandler project

Adding a reference to an existing project

Open the code view of the application (TestApplication.cs) and add the following using statements:

using System.Reflection;
using System.IO;

Drag a TextBox onto the form and call it txtPlugin
Drag a Button onto the form and call it btnBrowse
Drag a Button onto the form and call it btnLoad
Drag an OpenFileDialog onto the form and call it ofdPlugin

This is how it could look like

Double click the btnBrowse button and add the following code:

private void btnBrowse_Click(object sender, EventArgs e)
{
        ofdPlugin.Filter = "Plugin | *.dll";
        ofdPlugin.FileName = "";
        ofdPlugin.CheckFileExists = true;
        ofdPlugin.FileOk += new CancelEventHandler(ofdPlugin_FileOk);

        ofdPlugin.ShowDialog();
}

Add the following method aswel (This is the ofdPlugin.FileOk event handler)l:

private void ofdPlugin_FileOk(object sender, CancelEventArgs e)
{
        if (e.Cancel == false)
        {
                txtPlugin.Text = ofdPlugin.FileName;
                btnLoad.Enabled = true;
        }
}

The above code will show an open file dialog when you click the browse button, allowing you to select the plugin you wish to load.
When you’ve selected the DLL you wish to load and it’s a file that exists, it’ll show the full path to the file in the textbox and enable the load button.

Now double click the btnLoad button and add the following code:

private void btnLoad_Click(object sender, EventArgs e)
{
        this.LoadPlugin(txtPlugin.Text);
}

Now, if you honestly thought that it would be thΓ‘t simple, you’re wrong ^.^
Before all of that works, we’ll need some extra code that acutally deals with the whole plugin loading thing:

// Code snippet for loading the plugin
        private void LoadPlugin(string p_sPlugin)
        {
            try
            {
                FileInfo fiPlugin = new FileInfo(p_sPlugin);
                Assembly assembly = null;
                string typeName = string.Empty;
                Type pluginType = null;

                assembly = Assembly.LoadFile(fiPlugin.FullName);

                if (null != assembly)
                {
                    foreach (Type type in assembly.GetTypes())
                    {
                        if (type.IsAbstract) continue;
                        if (type.IsDefined(typeof(PluginAttribute), true))
                        {
                            pluginType = type;
                            break;
                        }
                    }

                    if (null != pluginType)
                    {
                        ((IPlugin)Activator.CreateInstance(pluginType)).ShowPlugin();
                    }
                    else
                    {
                        this.ShowError(fiPlugin.Name + " is not a valid plugin." + Environment.NewLine + Environment.NewLine + "(Invalid plugin type)");
                    }
                }

            }
            catch (System.InvalidCastException)
            {
                this.ShowError(fiPlugin.Name + " is not a valid plugin." + Environment.NewLine + Environment.NewLine + "(Missing interface)");
            }
            catch (System.BadImageFormatException)
            {
                this.ShowError(fiPlugin.Name + " is not a valid plugin." + Environment.NewLine + Environment.NewLine + "(Invalid .NET Assembly)");
            }
            catch (System.Exception ex)
            {
                this.ShowError("There was a problem loading " + fiPlugin.Name);
            }
        }

The above method will do the following things:

It will first check if we managed to load the assembly information of the DLL file.
After that it goes over each Type from the DLL and checks if it is an abstract type and if the type equals our PluginAttribute.

When thats the case it will load the Plugin using the ShowPlugin() method πŸ™‚

There we go, that’s it πŸ™‚
Run the application, select the plugin we created and load it! (Make sure you hit ctrl + shift + b first so that it builds our entire solution)

If you have encountered any errors during this tutorial, please let me know so I can correct them πŸ˜‰
But as far as I know there shouldn’t be any πŸ˜€

Enjoy!

– Dirk

One thought on “Creating plugins in C#: The Application (Part 4/4)”

  1. (I’m writing from my phone, sorry for any spelling mistakes)

    First of all, very nice tutorial.

    Second of all: debugging isn’t that hard, the debugger should just step into ShowPlugin().

    Third: you van use [Plugin] instead of [PluginAttribute], anything between [] IS an attribute (if followed by a class/methid….) so the preprocessor just appends Attribute for your convience.

    Lastly: what you are doing is actually dependancy injection, without a framework, you are injecting your code where the application just has a blank.

Leave a Reply

Your email address will not be published.

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.