Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Managed Extensibility Framework

4.67/5 (7 votes)
9 Feb 2010CPOL3 min read 34.7K   470  
MEF is the Framework which allows you to load extensions to your application easily. It does discovery and composition of parts you need to be included in your application at run-time. You could extend your behavior simply by adding a new Plugin.

MEF is the Framework which allows you to load extensions to your application easily. It does discovery and composition of parts you need to be included in your application at run-time. You could extend your behavior simply with adding a new Plugin. Managed Extensibility Framework will do everything for you.

Hello MEF World!

Assume we have a really simple application and we want it to say "Hello MEF World!":

C#
class Program
{
    static void Main(string[] args)
    {
        var program = new Program();
        program.Run();
    }

    private void Run()
    {
        ProgrammGreeter.SayHello();
    }

    protected IGreeter ProgrammGreeter{ get; set;}
}

public interface IGreeter
{
    void SayHello();
}

public class Greeter:IGreeter
{
    public void SayHello()
    {
        Console.WriteLine("Hello MEF World!");
    }
}

That is absolutely how this looks and we want to make this work. The main issue is to have instance in property ProgrammGreeter to be real instance of Greeter (i.e. we need to inject that dependency).

Let's Accomplish This Goal with Managed Extensibility Framework

In order to do this, we need to include a reference to System.ComponentModel.Composition.

Accordingly to MSDN: "MEF is an integral part of the .NET Framework 4 Beta 1, and is available wherever the .NET Framework is used. You can use MEF in your client applications, whether they use Windows Forms, WPF, or any other technology, or in server applications that use ASP.NET. In addition, there are plans to add MEF support for Silverlight applications."

Most likely Managed Extensibility Framework will be included in .NET Framework 4.0, but for now we could download it from CodePlex site here.

Once we added reference, we could add Import and Export attributes.
Export stands for exposing some capabilities and Import stands for dependency on some other capability.

Our Greeter provides some capabilities so we add Export there:

C#
[Export(typeof(IGreeter))]
public class Greeter : IGreeter

We want to use that capability in our Programm class, we depend on that functionality. Add Import:

C#
[Import]
protected IGreeter ProgrammGreeter { get; set; }

Usually our capabilities live in other assemblies, but they could also live in called assembly. Anyway we need to say how to compose all our dependencies to MEF.

This could be done with method Compose which we be calling before we are using capabilities, usually at the start of the app:

C#
private void Run()
{
    Compose();
    ProgrammGreeter.SayHello();
}

private void Compose()
{
    var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
    var compositionContainer = new CompositionContainer(assemblyCatalog);
    compositionContainer.ComposeParts(this);
}

I ran my application and got:

How Does Managed Extensibility Framework Work?

I think that you are bit concerned/confused regarding that Compose method. Just read comments in code of Compose, which I made more detailed:

C#
//We need guide MEF how to Compose all we need
private void Compose()
{
    //Catalog says where to search for capabilities (Where do exports live)
    var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
    //CompositionContainer holds defined dependencies and coordinates creation
    var compositionContainer = new CompositionContainer(assemblyCatalog);

    //CompositionBatch object holds references to all objects that
    //need to be composed
    var compositionBatch = new CompositionBatch();
    //one of such objects is Programm instance (this), it needs to be composed
    compositionBatch.AddPart(this);

    //And finally Container has method called Compose to do actual Composing
    compositionContainer.Compose(compositionBatch);
}

In Managed Extensibility Framework, there are primitives called ComposablePart which hold extensions to your application grabbed from Catalog. But it might also be that they have Imports which also needed to be composed.

Take a look at this picture from Managed Extensibility Framework Wiki page.

More Complex Example

In this example, we will have application which parses XML file (contains information about some developer). Then when we want to deploy our application to Clients, we want that XML to pass some rules, but they could differ from Client to Client. To accomplish this, we put rules into separate DLLs and will work with it as with plugin.

We have two assemblies:

  • MEF.DEMO which declares ISecurityRule and IDataRule
  • MEF.Rules has implementation of those interfaces

Like in the picture below, I simply don't want to bore you with explaining of Rules logic. If you want sources, just ping me.

Our Programm class wants to load rules from other assembly, so we put Imports.

C#
[Import]
public ISecurityRule SecurityRule { get; set; }

[ImportMany]
public IDataRule[] DataRules { get; set; }

public void Run()
{
    Console.WriteLine("Programm run.");
    Compose();
    Console.WriteLine("Composition completed.");

    var document = XDocument.Load("developer.xml");
    Console.WriteLine(document.ToString());

    var passesValidation = SecurityRule.PassesValidation(document);
    Console.WriteLine(string.Format("Rule {0}: {1}",
                SecurityRule.GetType(), passesValidation));

    foreach (var d in DataRules)
    {
        var valid = d.IsValid(document);
        Console.WriteLine(string.Format("Rule {0}: {1}", d.GetType(), valid));
    }
}

As you noticed, we are using ImportMany, name says for itself.

We need to change our Compose method to search for Exports in Directory where execution assembly is located. For that, we use DirectoryCatalog.

C#
private void Compose()
{
    var catalog = new DirectoryCatalog(Environment.CurrentDirectory);
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);
}

Put those DLLs in one folder, and run MEF.DEMO. You will get:

The goal of MEF is to seamlessly glue together classes which import services from other parts of the application, and some classes which export those services. You could say that MEF is like DI container. Yes it has a lot of it, but Managed Extensibility Framework is concentrated on composition. And that composition could be done at run time at any point of time you want that to happen. Also you could do re-composition whenever you want to do that. You could load capabilities with Lazy technical or add some metadata to your exports. Discovering of dependencies in Catalog could be done with Filtering.

Managed Extensibility Framework is a great feature that Microsoft added to .NET 4.0 Framework.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)