No, this is not another introduction post. Being one of the earliest adopter of MEF, I started to see a great confusion around what MEF is, and what it really is suppose to do in this wild world of DI containers… Well ok, I can’t lie anymore about, as people have twitter proofs to throw at me, I was a part of that confusion :
As you see, I was pretty biased as an avid DI user, that MEF is an IoC container so why doesn’t it behave in a normal DI ish way ? I was seeing MEF as an only IoC container so much, and in that limited perspective its design has sucked big time for me, especially because of the unnatural Export - Import system. And for that matter, I even implemented a way of an external configuration for MEF.
This has proven to be really painful. Glenn Block, saw my pain through twitter and called me for an hour of a very nice and informative chat.
Here is the result: MEF is not a DI container. DI is only a part of the solution that MEF tries to bring into the scene. Ayende just got quicker in the game, and explained it well, so I couldn’t have the joy of telling the world first
I won’t repeat what Ayende said, I’ll just try to make things a bit more concrete in perspective of my understanding as a person who likes to talk over examples.
Understanding MEF with an example
Now, it is time to take those DI glasses off and look at a different view. Forget about DI, containers, IoCs et all. Let’s start thinking with a concrete example we all know about. Visual Studio has a plug in infrastructure. Say that we are handed to build that, what do we do ?
First, we need to come up with an interface (be it an SDK or API reference), sort of a hook to outside, so addin implementors can code against it.
This involves the lifecycle of the addin. You should be able to achieve basic needs create instance / retrieve already created one (singleton).
We should be able to provide a way of interact with add-in. Add-in should be able to easily send you messages about, say show solution explorer or open a file in editor.
We should be able to lazy load it if needed. E.g there is no need to load an add-in at start up when the add in is supposed to be performing within a context menu event.
A new add-in, or a replace of an old one should be as easy as throwing the dll in bin folder. This means that if a new set of addins is in place, you need to be able to choose amongst them. (meta-data based discovery)
When an add-in is replaced or simply dead, we need to unload it.
So in all this sense, VS is a composite application. It needs to be composed dynamically.Beware, during all these steps we still don’t care about the actual add-in. We just care that if it complies to our needs that we specified in the contract. We need something that quacks, and looks like a duck. Anything that supplies these demands, even if it is a dog, more than welcome to be part of our Visual Studio.
Now, these are all huge works. Imagine just lazy loading of a component has a lot of edge cases already(#3), let alone solving the unloading problem from AppDomain(#5). But let’s say that we finished and shipped our Visual Studio. Happy days, counting the money.
And now, we are assigned on a new task and writing Lutz Roeder’s great tool Reflector. And guess what, Lutz Roeder wants us to implement an add-in infrastructure so that they can perform several tasks in reflected code. To accomplish this, we need to do ALL the steps above again, from 1 to 5. All that drudge work, and none of it is reusable because we designed it in an application specific way (and that perfectly makes sense since our concern was not to build that framework). Now you got the point: MEF is a core .NetFx component that adds ability of composability to any app by default. Its aim in short term is, not replacing IoC containers but working with IoC containers, which fits this greater vision.
Another Example - Publisher Subscriber
A lot of confusion is also going around between MEF and System.Addin Namespace, similar to the confusion addressed above. Let’s look at another example that has nothing to do with add-ins, to show that problem is not an add-in bound system.
Say we have a banking system, with a strong domain model. We need services like Accounting, Personal Info, Leasing etc. And in this bank, in every two weeks or so there comes a new service.For the discovery and configuration of these new services, you would normally use an ESB (Enterprise Service Bus). That discovery part has indeed very similar roots with MEF. MEF provides you a lightweight bus-alike approach for your extensions. By hosting MEF, you are delegating this discovery system to MEF, and it provides you a rich Meta Data to be used. The Export - Import model indeed looks very similar to Publisher and Subscriber model in this sense.
MEF is by no means a replacement to today’s IoC containers, nor to System.Addin . It aims to be a reusable solution to provide a common base for the heavy lifting code of extensible applications, so we (hopefully) will need to worry less about extensibility concerns of the application. If you like, you can use MEF as your IoC container, but this doesn’t mean that you should. We can also use our favorite IoC container of choice with a free (as in speech) collaboration with MEF by Resolvers.I am planning to cover the concepts with a hands on application which will hopefully help to build better understanding, stay tuned.