Friday, January 28, 2011

Important Classes in MEF

MEF is great. It is one of the best things that has come along in .NET 4.

Just reading the greatest beginner tutorial on MEF ever : http://blogs.msdn.com/b/brada/archive/2008/09/29/simple-introduction-to-composite-applications-with-the-managed-extensions-framework.aspx

Class names have changed in the release version of MEF that comes with .NET 4 in the System.ComponentModel.Composition namespace. Also while going through it I cannot help but think that I am not absorbing all of it. Generally the best idea to make sure you learn something is to write it down.
So here is my attempt:


Concepts
Exporting:
MEF works on attributes.
For exporting data you just mark the property you want to export with [Export] attribute
By default it will take the property type as the key to export. So you will generally want to [Export("Foo")]
e.g
[Export("Foo")]
public string Foo{get;set;}

Importing:
At the target you have an option of either [Import("Foo")] or [ImportMany("Foo")] depending on whether there will one Export or many Export items contained in catalogs (explained next).
e.g
[Import("Foo")]
public string Foo{get;set;}
OR
[ImportMany("Foo")]
public IEnumerable Foo {get;set;}

If multiple exports are found but you only have an import an exception is thrown in Compose (explained below)

Catalog:
First you make a catalog. This will contain a list of places that will Export the data you need.
Types of catalogs (Contained in System.ComponentModel.Composition.Hosting). Overload Constructs can be found at the MSDN documentation as linked:

  • AggregateCatalog(); For collecting a number of catalogs into one. 
    • Usage:
      var catalog = new AggregateCatalog();
      catalog.Catalogs.Add(othercatalogs); 
  • DirectoryCatalog(string directoryPath);
    • Usage: The string directoryPath can also be relative URLs. 
  • AssemblyCatalog(Assembly assembly);
    • Usage: generally will load the current assembly in this (Assembly.GetExecutingAssembly()). Since foreign assemblies are better loaded through DirectoryPartCatalog. 
CompositionContainer
After you have all your catalogs (either one of DirectoryPartCatalog/AssemblyCatalog or a combination of them as AggregateCatalog) you will load them into a composition container:

var container = new CompositionContiner(catalog); 

Finally Fix Up the exports into imports: 
container.ComposeParts(this);

Where this will be the instance of a class where you have the Import attributes setup. 
If everything is fine you get no exceptions and your exports have been loaded into imports.
Note: ComposeParts is actually an extension method with params. So you can do : 
comtainer.ComposeParts(classInstance1,classInstance2);
etc. 

Enjoy!