Programming Microsoft ASP.NET 4 - Dino Esposito [300]
MEF vs. IoC
MEF does some work that any IoC does. Like an IoC framework, MEF is able to spot dependencies and resolve them, returning a usable graph of objects to the caller application. In raw terms of functionality, MEF is not as powerful as most IoC tools. MEF has limited support for managing the object’s lifetime and doesn’t currently support any form of aspect orientation. MEF also requires that classes it deals with be decorated with ad hoc attributes.
You can’t just take a plain old CLR class and use it with MEF. On the other hand, MEF swallows exceptions when some particular things go wrong during the composition process.
In summary, MEF is an IoC framework optimized for the specific task of discovering and loading optional and compatible components on the fly.
Should You Choose MEF or an IoC?
MEF is already in the .NET Framework 4; any IoC tools of choice is a separate set of assemblies and adds dependencies to the project. MEF is available only for .NET 4, whereas most IoC frameworks are available for most .NET platforms. This said, however, I’d like to remark that MEF doesn’t bring new significant capabilities to the table that you couldn’t code yourself or achieve through an IoC. MEF, however, makes writing plugin-based applications really fast and simpler than ever before.
If MEF serves all your IoC needs, choose MEF and code your way within the .NET Framework 4. If you’re happy with the IoC you’re using today, perhaps there’s no need for you to change it. In this regard, MEF won’t give you an ounce more than your favorite IoC.
The real issue is when you want to use MEF because of plugins but still need to mix it with an IoC because MEF doesn’t offer the advanced services of rich IoC—for example, call interception. In this case, either you drop MEF in favor of IoC or configure MEF to accept instances created by the IoC of choice.
MEF in Action
An MEF application is based on components known as composable parts. Each part can contain some members decorated as imports. An import is a class member with the Import attribute, and it indicates a member that will be resolved and instantiated by the MEF runtime. In a MEF application, you also find classes decorated as exports. An export is a class decorated with the Export attribute. An instance of an export class can be used to perform an import as long as the import and export match.
What does determine a valid match?
An import/export match is based on a contract. A contract here has little to do with service or interface contracts. An MEF contract is a collection of meta information that both imports and exports contain. In most cases, it is a simple string. In other cases, it contains type information or both unique strings and type information.
The list of exports is determined by catalogs. A catalog is a provider that returns the list of available exports to be matched to the imports of the object being resolved. Finally, the composition process is the process in which all imports (that is, dependencies) are resolved.
Here’s a brief code example to illustrate:
public class PasswordCreator
{
private CompositionContainer _container;
public ProgramBody() {
InitializeMef();
}
private void InitializeMef()
{
var catalog = new DirectoryCatalog("Plugins");
_container = new CompositionContainer(catalog);
// Fill the imports of this object
try {
_container.ComposeParts(this);
}
catch (CompositionException compositionException);
}
[Import]
public IPasswordFactory PasswordFactory { get; set; }
public String CreatePassword()
{
if (PasswordFactory == null)
{
return "Dependency not resolved.";
}
return PasswordFactory.Create(12);
}
}
The class PasswordCreator generates a random password using the services of an object that implements the IPasswordFactory interface. No such a component, though, is instantiated by the class itself. The task, in fact, is delegated to MEF.
MEF will use a directory catalog to