Over a million developers have joined DZone.

First Encounters of the MEF Kind

DZone 's Guide to

First Encounters of the MEF Kind

· ·
Free Resource

One of the newest additions to the .NET 4 framework is MEF. MEF stands for the Managed Extensibility Framework and is the answer to your prayers if you are building an app that allows developers to extend its functionality by building plugins.

MEF makes the task of loading assemblies and utilizing their functionality very simple. Before we go any further there are a few basic terms that you must understand before you start using MEF:

  • The Catalog is responsible for loading assemblies. There are several types of catalogs to chose from such as DirectoryCatalog and AssemblyCatalog which we will discuss in more detail later on.
  • The Container holds one or more catalogs.
  • The Export attribute is used to decorate objects so they can be consumed by MEF.
  • The Import attribute lets MEF know that an object is the target for one of more exported objects.
  • A part is any object that is exported or imported.

So in order to start using MEF, you need to create one or more catalogs, add them to a container and then call a method named “ ComposeParts” which will search the assemblies in the catalog for “ parts” which are marked with export or import attributes. In order to help understand the process better, lets look at some code..

A Real Life Example:

All the code you are about to see has been taken from my WeBlog project on Codeplex. WeBlog is a next generation blogging platform written in MVC 2 and .NET 4.0. I am using MEF in WeBlog to take care of loading widgets like Tag Clouds and search boxes. Here is a screenshot:

In order to get things started, I first needed to create a WidgetModel class. Here is the declaration:

    public abstract class WidgetModel {
public Guid? ID { get; set; }
public abstract string Name { get; }
public string Title { get; set; }
public Boolean ShowTitle { get; set; }
public string[] AllowedRoles { get; set; }

public WidgetModel() {
AllowedRoles = new string[] { };

To make a widget, I inherit from the WidgetModel class and override a few properties. Then I mark the class with the Export attribute so MEF can find it later on:

public class SiteAdminWidget : WidgetModel {
public SiteAdminWidget() : base () {
Title = "Site Admin";
AllowedRoles = new string[] { "admin" };

public override string Name {
get {
return "SiteAdmin";

At the heart of WeBlog, I have the WidgetManager class which is responsible for loading widgets from the assemblies. When the WidgetManager class is instantiated I call the DiscoverWidgets method. The DiscoverWidgets method creates an aggregate catalog. An aggregate catalog is used when you need to search multiple locations for parts in MEF. In this case, we used an AssemblyCatalog and a DirectoryCatalog. In particular, this code is adding the currently executing assembly to the container in addition to all the files in the Widget directory which end in “Widget.dll”. Once the catalogs are created, we add them to the CompositionContainer. Then we call ComposeParts on the container object, which finds all the objects decorated with import or export attributes.

    namespace WeBlog.Extensibility {
public class WidgetManager {
private IDataProvider _provider = Engine.GetProviderInstance();
private static CompositionContainer _container;
private const string WIDGET_PATTERN = "*Widget.dll";
private AggregateCatalog _catalog;

public IEnumerable<WidgetModel> Widgets { get; set;}

public WidgetManager() {

private DirectoryInfo WidgetDirectory {
get {
return new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Widgets"));

private void DiscoverWidgets() {
//search the widget directory and also the current assembly for Widgets
_catalog = new AggregateCatalog(
new DirectoryCatalog(WidgetDirectory.FullName, WIDGET_PATTERN),
new AssemblyCatalog(Assembly.GetExecutingAssembly()));
_container = new CompositionContainer( _catalog );

When this code executes, MEF will find the objects marked with the export attribute. In addition, MEF will also discover any objects marked with Import attributes and match them up with the exports. In my case I have three WidgetModel objects being exported and one property being imported (WidgetManager.Widgets). Since the ImportMany attribute is an IEnumerable list of WidgetModels, MEF will take all the exported WidgetModels and assign them to the Widgets property for us automatically. Alternatively, if you do not want to automatically assign objects to a property then you can always query the container yourself. Since each composable part in the container has metadata associated with it you can use LINQ to return the objects you desire.

Once the Widgets property is loaded, I can enumerate over the list and display them on the page:

    <div id="page">  
<div id="content">
<div class="posts">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
<div id="sidebar">
<% foreach (var widget in Engine.WidgetManager.Widgets) { %>
<%= Html.RenderWidget( widget ) %>
<% } %>

Just for clarification, RenderWidget is an HTMLHelper that I wrote, which is functionally similar to the RenderPartial method. It takes a WidgetModel object as an argument and displays it on the page. However, it wraps the contents of the Widget with some additional html tags that are used to delete, move and edit the widget data from the user interface.

Additional Resources

If you want to learn more about MEF then here are a few sites which you may find useful:

Finally, if you start using MEF and you get stuck then try asking for help on Twitter. While I was putting together some code for WeBlog I posted a message about MEF on twitter using the #MEF hash tag. I was very excited when Glenn Block ( @gblock) responded. Glenn is the primary developer on the MEF project. In any case, it is apparent that Glenn is very passionate about MEF and very responsive to questions. He has put together a excellent library and we should all be thankful for his hard work. Thanks Glenn!

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}