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!":
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:
[Export(typeof(IGreeter))]
public class Greeter : IGreeter
We want to use that capability in our Programm
class, we depend on that functionality. Add Import
:
[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:
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:
private void Compose()
{
var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var compositionContainer = new CompositionContainer(assemblyCatalog);
var compositionBatch = new CompositionBatch();
compositionBatch.AddPart(this);
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
.
[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
.
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.