Composition using MEF


With .NET 4.0 Microsoft ships a new composition container named Managed Extensibility Framework (MEF). MEF already have two feathers in the cap: Visual Studio 2010 editor extensions and Intellipad, the DSL editor of OSLO SQL Server Modeling.

MEF can be used to achieve the object-oriented programming  principle “Open-Closed Principle (OCP)”  software entities (classes, modules, functions, etc.) should be open for extension, but closed for modifications. What that means to me is that it should be possible to extend the application without modifying its case. For example, if an application was programmed to log to an text file and a later point of time if the requirement is to write to a console, then it should be possible to do so without modifying the source code. To achieve OCP we need to provide extension points. We can found a lot of such examples in the addin model of the applications like Visual Studio text editor, Outlook, WinAmp etc.


The fundamental concepts in MEF are : Import, Export, Composable Part, Contracts, Composition. The following diagram shows how they are related :



A Composable Part should have at least one or more Export or Import. Imports and Exports are defined using Contracts.  A catalog of parts is used by container to compose the parts. Lets see a simple example of this.


Let’s define a contract first for the Imports and Exports. I have a ILogger interface as contract.

Code Snippet
  1. public interface ILogger
  2.     {
  3.         void Debug(string message);
  4.         void Error(string message);
  5.         void Warn(string message);
  6.     }


A ConsoleLogger class which implements ILogger and writes to the Console.

Code Snippet
  1. using System;
  2. using System.ComponentModel.Composition;
  5. namespace CdcSoftware.Loggers
  6. {
  7.     [Export(typeof(ILogger))]
  8.     public class ConsoleLogger : ILogger
  9.     {
  10.         #region ILogger Members
  12.         public void Debug(string message)
  13.         {
  14.             Console.WriteLine("[DEBUG] " +  message);
  15.         }
  17.         public void Error(string message)
  18.         {
  19.             Console.WriteLine("[ERROR] " + message);
  20.         }
  22.         public void Warn(string message)
  23.         {
  24.             Console.WriteLine("[WARN] " + message);
  25.         }
  27.         #endregion
  28.     }
  29. }


At line no. 2 the we import System.ComponentModel.Composition namespace from the references assembly System.ComponentModel.Composition one of the MEF assembly. This is required for the ExportAttribute used at line no. 7. By using Export attribute we have exported the ConsoleLogger as a composable part .

Now we have a contract and an export. Lets see the code to import. To import we need to use the ImportAttribute like this. 

Code Snippet
  1. [Import(typeof(ILogger))]
  2. public ILogger Logger { get; set; }

Now lets compose it.

Code Snippet
  1. using System.ComponentModel.Composition;
  2. using System.ComponentModel.Composition.Hosting;
  3. using System.Reflection;
  5. namespace CdcSoftware.Application
  6. {
  7.     public class ComposedApplication
  8.     {
  9.         [Import(typeof(ILogger))]
  10.         public ILogger Logger { get; set; }
  12.         public static void Main(string[] args)
  13.         {
  14.             ComposedApplication app = new ComposedApplication();
  15.             app.Run();
  16.         }
  18.         private void Run()
  19.         {
  20.             Compose();
  21.             //now the application dependency is composed
  22.             Logger.Debug("This is a debug message");
  23.         }
  25.         private void Compose()
  26.         {
  27.             AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  28.             CompositionContainer mefContainer = new CompositionContainer(catalog);
  29.             mefContainer.ComposeParts(this);
  30.         }
  32.     }
  33. }


On start of the ComposedApplication, the first thing we do is to compose it as in line 20. For this application since all the required parts viz. Imports and Exports, are in the same assembly I am using AssemblyCatalog at line no 27 and initializing with the executing assembly. Then the CompositionContainer is instantiated with this catalog as constructor parameter. To get the dependency fulfilled or the part composed, we need to call the ComposeParts method on the container as in line 29.  After the composition succeeds, all the imports the current class will be fulfilled like the Logger property.


References :

Where is Python absolutely necessary in Intellipad?

Managed Extensibility Framework in the Editor


Leave a Reply

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

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

Google+ photo

You are commenting using your Google+ 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