0 Comments

Our current plugin sample application has one big shortcoming: The plugins can’t communicate with the main application. Showing message boxes won’t take us very far.  It’s common that a plugin requires something from the main application. That something can be a query for the application status or a request to show something on the screen. Plugins rarely survive alone. In this post we’re going to extend our sample application to allow plugins to interact with the Windows Forms client.

First, let’s define an interface for our plugins. Our plugins don’t require much from the application but it would be nice if they could print something on the screen instead of showing the message boxes. We can start from this:

   1: public interface IApplicationFeatures
   2: {
   3:     void ShowOnScreen(string message);
   4: }

Then let’s add a textbox in our app’s screen. This is where the plugins can send their messages. Here’s a screen capture from our new application:

plugin_msg

Now we need just two things:

  1. A class that implements the IApplicationFeatures-interface
  2. Some way to pass a reference of this class into our plugin

Let’s start from the first point. Because our needs are so straightforward, there’s no need to create a new class: We can use our existing MainApplication-class and make it implement the IApplicationFeatures-interface. Here’s the full implementation:

   1: public void ShowOnScreen(string message)
   2: {
   3:     this.messageFromPlugin.Text = message;
   4: }

If one of our plugins require an IApplicationFeatures-implementation, we want to pass it our MainApplication-class. For this to work, we must make sure that the MainApplication is a singleton and that the Structuremap resolves the same instance for calls for IApplicationFeatures and IMainApplication. Thanks to Structuremap, this is easy to configure. Change the CreateContainer in our Program.cs to the following:

   1: private static IContainer CreateContainer()
   2: {
   3:     var container = new Container(x =>
   4:                                       {
   5:                                           x.AddRegistry<PluginRegistry>();
   6:                                           x.For<IMainApplication>().Singleton().Use<MainApplication>();
   7:                                           x.Forward<IMainApplication, IApplicationFeatures>();
   8:                                       });
   9:
  10:     return container;
  11: }

Now, every time a class requires either IMainApplication or IApplicationFeature, the same instance is used.

After this it’s very easy to pass the reference into our plugins. Remember how our plugins are resolved by the Structuremap container? This means that we can use constructor injection. We’re going to just add the required interface into our plugin’s constructor and let the Structuremap do all the hard work. Here’s the full implementation of our plugin:

   1: public class MyPlugin : IPlugin
   2: {
   3:     private readonly IApplicationFeatures appFeatures;
   4:
   5:     public MyPlugin(IApplicationFeatures appFeatures)
   6:     {
   7:         this.appFeatures = appFeatures;
   8:     }
   9:
  10:     public void Run()
  11:     {
  12:         appFeatures.ShowOnScreen("Hello from plugin.");
  13:     }
  14: }

And here’s the result after running the program and clicking the only button:

hello_plugin

Now your plugins don’t have to survive alone.

Download

The full source code is available from the GitHub.