BLOG

Hook style extensions using Mef and Unity

Wed, 02/16/2011 - 19:29

Hi, in my last post I wrote about how making an application maintainable, or at least how to help that principle, the other goal we have in that same application is to make it extensible.

There are several ways and approaches but after taking a look to a couple of those I decided to use Managed Extensibility Framework or MEF for short (http://mef.codeplex.com).

MEF is a really cool library to simplify extensibility issues for .Net applications; it is based on a DI container and composition to resolve objects with unknown possible extensions. At first look this might look pretty close to Unity, but although it shares many DI principles, MEF lacks some important features that Unity has, but Unity lacks some others that MEF has. MEF it is solely focused on extension / composition of objects, its goal is to extend apps by simply dropping a binary file into a folder, by discovering objects and connecting them to others that need those, that’s it; while Unity is more focused on Inversion of Control, maintainability, not extensibility.

So, briefly, with MEF I can declare objects as Exports, and Import them into other objects without even knowing they exist, simply this way I have an extensible application, but this is just an idea, not a real case where I’m extending my app, the purpose of this post is to show you a very simple example of how can I extend my app with a “Drupal Hooks” style, or something close to it Smile

The idea is to provide my app with the ability of extending its behavior at some particular point, if we should draw this as a flowchart it would be very close to this:

 

After Step 2, if there is any Additional Step “Hooked”, then before continuing all those objects must do their stuff first. 
This is very helpful since there is a pretty big chance that I will need to extend many portions of my project in the future, but... changing the main flow of my processes? Hmmmm no… I don’t think so, at least it is working properly. So what do you think? Extending my app by just simply coding a new step and hooking it there is pretty cool right? Ok now to the code…

The idea is to create a Notifications service that creates “messages” for users, but after creating those messages we want to be able to extend its behavior.
First of all to be able to import objects, MEF needs to declare those classes as Exports, but wait… we might not know which classes we might have in the future… so we need an interface to define a contract, we don’t know what those future classes will do, we just let them do their job.

So here it is:

{syntaxhighlighter brush:csharp} namespace Definitions.Hooks { [InheritedExport] public interface INotificationSendHook { void DoWork(Model.notifications notification); } } {/syntaxhighlighter}
The InheritedExport attribute means that MEF will look for all classes implementing that Interface or class, so having this interface we ensure that it doesn’t matter which class will perform the task, it will do it.
Now, let’s work on the NotificationService class, first of all we will need to have a list of objects implementing our bran new INotificationSendHook interface, we will call that property “Hooks” (very inventive name BTW Smile ) 
{syntaxhighlighter brush:csharp} public IEnumerable Hooks{ get; set; } {/syntaxhighlighter}
Once we have this property declared in our object, we need to import all Hooks into it, this can be easily done with MEF Laughing
{syntaxhighlighter brush:csharp} IPluginsContainer container = CrossTools.UnityProvider.UnityProvider.Instance.Resolve(); Hooks = container.Container.GetExportedValues(); {/syntaxhighlighter}
The first line it’s a Unity class since I have a class between MEF and my app, just for maintainability, what you need here is just the MEF container and the GetExportedValues asking for the star of the show, the INotificationSendHook, MEF will do the rest.
Now, we want to define when our app will be extended, so lets decide it will be after sending our notification message.
{syntaxhighlighter brush:csharp} public bool CreateNotification(Model.notifications notification) { try { _repository.CreateNotification(notification); if (Hooks.Count() > 0) { foreach (Definitions.Hooks.INotificationSendHook hook in Hooks) { hook.DoWork(notification); } } return true; } catch(Exception ex) { _modelState.AddError("Create Exception", ex.Message); return false; } } {/syntaxhighlighter}
That’s all! Our Notification sending process is extensible! So let’s extend it… to do it we just need to create a new object that implements our nice Interface, here is a sample.
{syntaxhighlighter brush:csharp} public class MyHook : Definitions.Hooks.INotificationSendHook { public void DoWork(Model.notifications notification) { Model.notifications copy = new Model.notifications(); copy.text = "Copy of " + notification.text; copy.userid = notification.userid; repository.CreateNotification(copy); } } {/syntaxhighlighter}
Now we have our Hook here, the next step is to run the app and send a notification! After storing it into the DB, our Hook will take place and will make a copy of it, pretty silly but fair enough for a simple sample, what do you think?
In my next post (I hope) I will try to talk about how to make this Hooks safe for my main App.
Let me know what do you think about this!
.Net Developer
Senior developer interested in multitier architecture, web based, back-end and core app design and development.