Sunday 29 July 2012

MEF : Sample application and explanation

In this post we will create a sample application and we will try to understand the terms:

  • Parts
  • Import
  • Export
  • Composition
  • Catalog
  • Contract

Parts, catalogs, and the composition container

Parts and the composition container are the basic building blocks of a MEF application. A part is any object that imports or exports a value, up to and including itself. A catalog provides a collection of parts from a particular source. The composition container uses the parts provided by a catalog to perform composition, the binding of imports to exports.

Imports and exports

Imports and exports are the way by which components communicate. With an import, the component specifies a need for a particular value or object, and with an export it specifies the availability of a value. Each import is matched with a list of exports by way of its contract.
MEF is a part of the Microsoft .NET Framework, with types primarily under the
System.ComponentModel.Composition.* namespace.

The two namespace we normally add are:
  • using System.ComponentModel.Composition;
  • using System.ComponentModel.Composition.Hosting;
The other options possible are :


The core of the MEF composition model is the composition container, which contains all the parts available and performs composition. 

The most common type of composition container is CompositionContainer.

In order to discover the parts available to it, the composition containers makes use of a catalog. A catalog is an object that makes available parts discovered from some source. 

 MEF provides catalogs to discover parts from a provided type, an assembly, or a directory. Application developers can easily create new catalogs to discover parts from other sources, such as a Web service.

The call to ComposeParts tells the composition container to compose a specific set of parts, in this case the current instance of Program. At this point, however, nothing will happen, since Program has no imports to fill.

 Now, let us import an interface ICalculator inside the program class.
The definition is similar except for the , Import attribute. This attribute declares something to be an import; that is, it will be filled by the composition engine when the object is composed.
Every import has a contract, which determines what exports it will be matched with. The contract can be an explicitly specified string, or it can be automatically generated by MEF from a given type, in this case the interface ICalculator. 

Any export declared with a matching contract will fulfill this import.

The contract is independent from the type of the importing object. (In this case, you could leave out the typeof(ICalculator). MEF will automatically assume the contract to be based on the type of the import unless you specify it explicitly.)

Bow, let us add the interface that we are importing and let us also add a class which implements this interface.

Let us decorate this class with the Export attribute, export that will match the import in Program. In order for the export to match the import, the export must have the same contract.
Now that we have added imports and exports , we need to fill the container with this, so we add followinng to the program.cs

All the logic to calculate is written in FirstCalculator class, the interface ICalculate is implemented.
So, now all the tasks for the business logic is just in 1 place FirstCalculator.
Program contains the composition container which is filled with the required import.
So, now my work is to instantiate the composition container from my main method and use it.
This is a simple example which shows a single method import and export.

But when we are going to do a real calculator we will be importing methods for add, subtract , divide , multiply etc.
A single import method won't work in this case.

 An ordinary ImportAttribute attribute is filled by one and only one ExportAttribute. If more than one is available, the composition engine produces an error. To create an import that can be filled by any number of exports, you can use the ImportManyAttribute attribute.

A good tutorial for importmany is at importmany example.

A normal question which is raised many times is

My import isn't being set, what could be wrong?

Check :
  • Is the member (property or constructor) being imported public?
  • Field imports aren't supported, use properties instead
  • Is the imported member the exact same contract type as the export?


Happy importing-exporting

No comments:

Post a Comment