MEF is not An IoC container; but MEF uses IoC

Somehow I got on the conversion of MEF while chatting with Glenn Block. IoC came up in that conversion. I believe, at some point, I said something along the lines of MEF is not an IoC container; but MEF uses IoC. Someone else asked me to clarify that after the conversation. It’s a common misconception that MEF *is an* IoC container. I thought it might be useful to summarize those conversations for others.

Part of what gives MEF the ability to do what it does is most certainly IoC. Traditional dependencies (control) are inverted so that something (the host) doesn’t depend on a concretion (the extension, in the case of MEF) but an abstraction. The abstraction with MEF and IoC is an interface.

MEF manages extensions—dependencies—that may or may not exist at run-time but are rarely known/exist at compile-time. This needs to occur because you want 3rd parties to extend your application (of course, conceivably you must produce and publish your application before a 3rd party can even conceive of extending it). For any one dependency, MEF may be managing multiple extensions.

The difference with an IoC container is that it’s managing static dependencies: dependencies that must exist at compile-time in order for the application to correctly run at run-time. The impetus of IoC is different than MEF in that you don’t want to offer the ability to “extend” your application, but ensure that a particular class doesn’t have a direct coupling (or dependency) on another class. IoC doesn’t remove the dependency entirely, it just means the code can evolve independently. For the application to run correctly when deployed, it depends on ClassA being injected into ClassB at some point for that to happen. But, ClassA can compile without ClassB. This is always a one-to-one dependency.

If MEF were truly an IoC container then you’d expect be able to use an IoC container to extend an application at runtime—which is not the case.

To be clear, MEF uses the concept of Inversion of Control; but doesn’t use an external Inversion of Control container (that I’m aware of–I don’t know of any that support what MEF is trying to do).

One of the issues that MEF attempts to solve is the lack-of design/compile-time availability of the components that it’s loading. This isn’t generally a scenario that most IoC containers try to deal with. Most IoC containers assume that the loaded types are required by the application in order to continue and simply fail the application if they’re not. MEF supports extensions; extensions to existing functionality. So, MEF often deals with optional components, components that if are not available at run time the application is free to continue running.

The way you describe it, it is not that MEF is not an IoC container, rather it is more than an IoC container. Since you believe that MEF is not an IoC container, can you explain why you would not choose to use it as an IoC container?

@David. It’s not that MEF can’t be used as an IOC or a DI container, clearly it could be. And, in fact, some of the code examples for MEF show using it simply as a DI container.

MEF is about extensibility. Extending an application involves increasing its scope and to accept new functionality. A DI container is about decoupling and managing dependencies–dependencies that the software system needs in order to run. Dependencies are requirements known at design/compile time.

A system shouldn’t be dependent on extensions in order to run–clearly that’s not “extending” functionality. Yes, you must design DI into your system in order to support extensibility, because you can’t couple to components you don’t know exist. But, MEF doesn’t simply become a DI container because it manages injection of extensions.

I think you did make the point quite well. What a few people may be misconstruing is the difference between inversion of control and “Inversion of Control”. IoC is the name we give a particular method of managing dependencies; but something which inverts the control of dependencies is not necessarily an IoC container… the Composition Fallacy.

To summarise your article, I would say that:

A. An IoC Container uses the principles of Inversion of Control to loosely couple classes with their dependencies.

B. MEF is a framework which inverts the dependency structure of classes and extensions by inverting the control flow of dependencies.

“A” does not equate to “B” within these definitions, however they do produce similar end results if used in MEF’s most basic form. MEF takes the act of inverting control a step further than mere IoC and allows a whole IList of extensions to be used with one class at a time, which can all be manually swapped out, edited and changed by the end user, who could also remove all the DLL files and not jeapordise the integrity of the project.

The main point the author is trying to make, which I would like to reiterate in different words; IoC Containers are most useful when the extensions you are managing are critical to the project. The class, in this case, still depends on the information within the extension, even though the extension itself has been abstracted. If the project will fall over without at least one version of these extensions being present, an IoC Container should be used.

MEF, on the other hand, should be used when extensions are supplementary to the main operations of the project. If the project can stand with no extensions present then MEF can safely be used.