Plugin Framework

A lightweight plugin framework targeted at web applications. It uses MEF for composition.

Important
The framework is still in its infancy. It is alpha quality code, don't use it in production!

Quick Tutorial - Making of the Sample Application

Step 1

Created the solution and added the following projects:
  • MvcApplication - the main example. You can submit a message that will be processed by the active plugins if any.
  • ExampleAbstract - dll where the IPlugin interface is defined - used by the 3rd party plugin developer
  • Package1 - A project which contains 2 plugins

A Package is an assembly containing one or more plugins.

Both the ExampleAbstract and Package1 projects reference PluginFramework.Client and the IPlugin definition looks like this

public interface IPlugin:IPluginPart
{
	string Process(string text);
}

IPluginPart is a marker and all plugins must implement it.

Next I've implemented 2 plugins
  1. AddTime - adds the time to a text
  2. AddDate - adds the date to a text

[PluginInfo("Package1.AddTime", "Package1", "1.0", FriendlyName = "Add Time",Description = "Adds the current time to the message")]
public class AddTimePlugin : IPlugin
{
            public string Process(string text)
	{
		return string.Format("{1}<br /><span style=\"color:red\">{0}</span>", DateTime.Now.ToShortTimeString(),text);
	}
}

Our plugin implements the IPlugin interface and is decorated with the PluginInfo attribute. The AddDate plugin has similar implementation

Package1 is compiled and we have our package. Only the Package1.dll is needed for deployment.

Step 2

Created the Packages directory in the MVCApplication with the package.xml which tells what pakcages to load. Each package has to have its own directory with the name of the package and a manifest.xml file along with the package assemblies.

Step 3

Initialized the plugins in global.asax.cs
protected void Application_Start()
		{
			AreaRegistration.RegisterAllAreas();

			RegisterGlobalFilters(GlobalFilters.Filters);
			RegisterRoutes(RouteTable.Routes);
			InitPlugins(); //plugin framework initialization
		}

		public static PackageManager Packages { get; private set; }

		public static WebContextPluginsManager<IPlugin> ActivePlugins { get; private set; }

		private void InitPlugins()
		{
			PackageManager.PluginDirectoryPath = Server.MapPath(@"~\Packages");
			PackageManager.CachePluginDirectoryPath = Server.MapPath(@"~\App_Data\Cache");
			Packages=new PackageManager();
			Packages.LoadPackages();
			Packages.CreatePluginsManager(new InMemoryRepository());
			ActivePlugins=new WebContextPluginsManager<IPlugin>(Packages.PluginsManagement);
		}
Quick explanation: We need to setup the paths for the Packages directory and for the Cache directory, where the assemblies will be shadow copied and loaded.
Then instantiate the PackageManager (in a static variable, should be a singleton) and tell it to load the packages( configured in packages.xml). Then we create a plugins manager (which will handle the state of plugins). THe InMemoryRepository is a test/debug only repository implementation to save/load which plugins are active.

The last step is to istantiate a WebContextPluginsManager and this will be the class sued to hold the actually instances of plugins.

Step 4

I've created the PluginsController with views to show a list of installed plugins wiht the posibility of enabling/disabling them and a list of available packages.

To get a list of packages
ViewBag.Packages = MvcApplication.Packages.GetAvailablePackages()

To get a list of the available plugins
ViewBag.Plugins = MvcApplication.Packages.PluginsManagement.GetAvailablePlugins();

To enable/disable plugins
 	[HttpPost]
 	public ActionResult Index(PluginStateUpdater[] plugins)
    	{
			var al = MvcApplication.ActivePlugins;
			al.StateManager.UpdateState(plugins);
			//create instances for enabled plugins
			foreach(var p in plugins.Where(d=>d.IsActive))
			{
				if (p.IsActive) al.CreateInstance(p.Id);				
			}
    		return RedirectToAction("index","home");
    	}

That's it! Get the source and the sample application and see it in action.

The end.

Last edited Oct 24, 2011 at 6:42 PM by mike_sapiens, version 21