Tuesday, April 6, 2010

Ten Reasons to use the Managed Extensibility Framework

Leer: Diez razones para usar MEF.

One question I'm commonly asked is, "Why do I need the Managed Extensibility Framework? How do I know when to use it?" In addition to that really being two questions, I'm not sure I can tell you the top ten reasons to use MEF or whether or not it is the right tool for you. Instead, as a hands-on consultant who has been using MEF in production applications since the earlier previews, I can share ten reasons why I've used it in my development projects and prefer it over over other frameworks.

If you can relate to these ten items and are interested in learning more, check out my video series, Fundamentals of the Managed Extensibility Framework. Click the link to preview the lessons and learn more!

Reason One: It's out of the box.

While much of my work with MEF has been using the previews in Silverlight 3 projects, MEF is not just another side project or add-on. MEF will be part of the .NET Framework 4.0 Common Language Runtime (CLR). Just as we've grown accustomed to using generic lists or sending mail with the SmtpClient class, the Managed Extensibility Framework will be there, in the framework, out of the box. Developers will be able to simply include the namespace and go to work. No additional installs or grief over whether or not to include the bits with the application and worry about versions. It's an intrinsic part of the .NET framework which I believe will lead to fast adoption for the myriad problems it solves. I always prefer to use what is already there when I can, rather than tacking on third-party solutions unless they are absolutely needed.

Reason Two: Dependency injection and inversion of control.

This is the part that seems to confuse people when they ask, "Do we need another Unity?" MEF is far more than a substitute for dependency injection or inversion of control. However, it does manage DI and IoC quite well. With Unity, for example, I had to wire in a bootstrapper and configure the container, then either grab objects from the container to take advantage of constructor injection or explicitly request objects.

In MEF, the parts model makes it far easier in my opinion. I simply make IFoo available:

...
[Export(typeof(IFoo))]
public class Foo {}
...

And then ask for IFoo, and I'm practically done!

...
public class Bar 
{
   [Import]
   public IFoo Foo { get; set; }
}

I find this far easier to set up and manage consistently across large applications than worrying about when/where/how the container has been configured, whether or not I'm using a nested container, and then how to grab the desired implementation.

It also makes testing a breeze. I don't believe in unit testing multiple layers at the same time - if I'm testing Bar, I'm not going to test Foo again. So in this case, I can just set IFoo to a mock object and focus on Bar.

Reason Three: Lifetime management.

By default, imports will provide me with the same (shared) copy of classes that are exported by MEF. I'm not locked into this, however. I can easily override the lifetime of a class using a PartCreationPolicy. This is very important to me because often classes become mangled in order to support patterns like the singleton pattern: you have to hack the constructor and make it private, then supply a public method, and make all of this work in concert with your interface.

With MEF, I simply build a class and don't build lifetime management into the behavior of the class. Should the class know or care if it will live as a single copy, or have multiple copies running around? In most cases, the answer is, "No."

Reason Four: Configuration.

A side effect of lifetime management is that MEF gives me a very easy way to manage configuration information. I've seen it done many ways. In Silverlight, for example, you might be tempted to write a static class or even add properties to the main Application class to hold application-wide configuration data. To me, mangling the application itself in order to support this is wrong.

With MEF, I can simply implement an IConfiguration interface and import it wherever I need it. If I'm writing WPF or ASP.NET code, it's a simple matter in the implementation to parse an app.config or web.config file to load up the values. The consumers of this information, however, don't have to know (and quite frankly, don't care) how it got there. I have a setting for number of threads? Great, I import my IConfiguration and read that property. Done deal.

This is also great for testing, because I can supply an alternate configuration for my test environment.

Reason Five: Factories with dependency resolution.

This ties back to the part creation policies. One powerful feature of MEF is the concept of an ExportFactory. Unlike a direct import, an import of ExportFactory<T> doesn't give me T, but instead gives me a way to create T. This is important if I have a class that might get created multiple times.

If the class has dependencies, such as the configuration information I gave in the previous point, we need MEF to import and satisfy those dependencies. With the export factory, I can do this:

...
[Import]
public ExportFactory<IContract> Factory { get; set; }

public IContract MakeANewContract()
{
   return Factory.CreateExport().Value; 
}
...

Each time I make a new contract, all of the dependencies are wired in for me, so I don't have to worry about loading up the constructor or walking the dependency tree. MEF does it for me. For an example of this, take a look at my blog post Sequential Asynchronous Workflows using Co-routines (the view factory to "make" squares follows this pattern, as it must import the random number service).

Reason Six: ImportMany.

A common pattern in Silverlight and WPF applications is to have a region for some functionality, and then page through multiple controls within that region. For example, a wizard might occupy the main region of the page but actually use four different controls for each of four different steps in the wizard. MEF makes it easy to handle this pattern using ImportMany. I can ask for an IWizard and then retrieve a list of controls that satisfy the interface.

Another example is chain of responsibility and pipeline. The "weak link" in the chain is often that first "bootstrapper" class that has to wire in all of the links in the pipeline or chain of responsibility. The common implementation of this pattern is to have each link process and then conditionally pass processing along to the next link.

With MEF, I can easily import many instances of ILink and then either chain them together or use an iterator or other means to walk through the processes. Adding a new link is as simply as building the implementation, then exporting the class.

These are just a few examples of how powerful the ability to have multiple imports is.

Reason Seven: Strongly typed Metadata.

Of course, you might want to call classes in a particular order. Perhaps you export user controls and use an enumeration to specify where on the screen it belongs. Whatever your needs are, MEF allows you to supply strongly-typed metadata for your exports.

For an example of this, take a look at MEF instead of Prism for Silverlight. There I use the metadata to specify the types of views and regions, then wire them together using the region management pattern introduced by Prism.

Metadata can provide initialization information, routing information, and even priority information. For the Vancouver Winter Olympics, I built a synchronization tool that would scan primary and failover servers for live streaming. The tool generated lists of mismatched and/or missing files so the team at Microsoft could quickly react to ensure the integrity of the failover cluster and guarantee uptime. The tool created an XML document with the changes, then passed the document through a pipeline of modules. One module persisted the file to disk and updated a manifest. Another module would generate a CSV file, and yet another could email the document if certain alert criteria were met. I used MEF to pull in the modules, and metadata to tag the priority (for example, I wanted to persist the file to disk before specifying it as an attachment in the email program, so the module that saved the file had a higher priority than the module that would email it). When I needed another module, such as in testing, it was as simple as building it and exporting it to inject it into the pipeline.

Reason Eight: Extensibility.

MEF is unique in that it is designed specifically for extensibility. Many Dependency Injection/Inversion of Control solutions are designed to help you wire up what you know - "I have this instance, map it to this interface." MEF is designed to help you wire up what you don't know. It is extensible by nature and contains features such as stable composition that ensure your application can safely extend in realtime.

As an example (and for a fast introduction to MEF if this is new to you) take a look at my video, Build a Plug-in Architecture in Under 10 Minutes. I demonstrate building a console application using MEF. After I have the application running, I build a plugin, drop it into the target directory, and show how the application is able to pull in the new plugin in realtime without restarting. Now that's powerful!

Reason Nine: Modularity.

Along with extensibility comes modularity. This is especially important for Silverlight applications. Because these run in the user's browser, developers must take care to minimize the size of the file download as well as the client footprint. You don't want an application that takes 15 minutes to download or maxes out your customer's memory and CPU.

MEF allows for modularity by allowing you to separate functionality into different modules and load them dynamically as needed. This is done via the DeploymentCatalog. Imagine a large application that has ten menu items, but users typically may only go into one. This was the case for our Winter Olympics application that helped the Microsoft team monitor their environment. At any given time they might be pushing a configuration file, monitoring the live streaming servers, or performing other functions within the tool that were not interdependent on each other.

Instead of loading everything and having a huge XAP file, MEF allows you to split your applications into modules that load on demand. Only when the user needs a piece of functionality will their browser download the extension and make it available. This allows them to get up and running faster and conserves resources by only supplying what is needed.

Take a look at MEF instead of Prism for Silverlight Part 1 for an example of dynamic module loading.

Reason Ten: Customization.

Finally, I prefer MEF because it allows for customization. All of the parts are available to extend or customize as needed. Perhaps you are a fan of convention-based configuration and would rather use a provider-based model to wire in dependencies. It can be done.

I develop in Silverlight and am a fan of creating reusable behaviors to avoid duplicating code-behind or overloading view models where it's not needed. With MEF, this is very easy and straightforward. Take a look at Custom Export Providers with Custom Metadata for Region Management as an example. Using metadata, I wanted to take regions and route views similar to how Prism does it. Because MEF is extensible and customizable, I was easily able to build a behavior that would allow me to tag regions and export them with strongly-typed meta data in the XAML.

Of course, the customization doesn't stop there. Take a look at the MEF Visualizer Tool that can be injected into your project and generate DGML to visualize the MEF parts. Now that's powerful!

Conclusion

I'll conclude by saying that I'm very biased toward MEF. For good reason: I've been using it in enterprise applications and it has enabled me to build more composite, extendable, testable, and scalable applications faster and, in my opinion, better. If you're sitting on the fence wondering how MEF compares to other frameworks, I hope this guide will help you decide just how powerful it can be and how it might better fit your needs.

Please share your comments and feedback below. I'd especially love to hear if you are currently working on a MEF project and would like to share how it has helped (or perhaps hindered) you in the process. Thanks!

Jeremy Likness

17 comments:

  1. Great post to refresh me. Thank you.
    I wonder how to apply MEF with prism into my
    new project, and found your blog series for
    MEF iso prism. looks great and like to apply my
    project. You solved almost of all things what I
    need in prism except eventAggregation.
    Is there any link to be refered or your blogs I missed ?

    Thank you again...HK.Lee

    ReplyDelete
  2. Hi, thanks for your feedback! MEF doesn't have a direct "event aggregator" but supports it easily, whether you just want to use EA from the Prism library or something else like the messaging facility in MVVM light toolkit. Either way, the idea is that you have a pub/sub hub (wow, what poetry) and everyone get's access. So you could create IEventAggregator, with Publish and Subscribe methods, then anything needing it would simply import IEventAggregator and use those methods to publish and/or listen for events.

    ReplyDelete
  3. Jeremy
    Thank you for you many insights. I'm still teaching myself to program and from your post I see that MEF is a basic programming method, to be used everywhere and all the time. It just makes the whole "How do these objects talk to one another thing" drop dead easy!
    New to programming - learn MEF right alone with OOP!
    Thanks
    Mike Greenway

    ReplyDelete
  4. Mike, you're very welcome and glad this has helped you.

    ReplyDelete
  5. Jeremy,
    Thank you for your reply.
    I didn't touch MVVM light toolkit yet and like
    to stick to PRISM utill newer version comes in
    this fall. Will try EA in Prism.
    Thanks.

    HK.Lee

    ReplyDelete
  6. I came across this post via Google search and I must say it is very informative. This post has increased my curiosity about MEF and I am going to read each n every post related to it in your blog.

    Keep up the good work. Happy blogging!!!

    ReplyDelete
  7. Interesting how as your posts go on, you embrace MEF more and more!! That is very exciting. I am looking for a way to create a Drupal/DotNetNuke type framework for our applications using MEF, and it seems very possible from what you have said.

    ReplyDelete
  8. Hello Jeremy,

    I've just got up to speed with Prism/MVVM. I like Prism and mainly use it for building modular apps with the regions.

    It does get a little old creating up the modules & loading all the things into the container, defining the etc interfaces.

    Personally I use Sacha's Cinch framework because I really like the DataWrapper functionality.

    However, looking at the Import/Export attributes, it appears that MEF could save a lot of time.

    Have you stepped away from Prism completely? Could you think of anything that may cause you to have to use Prism over MEF.

    I most write LOB apps but the shell usually has to be extremely dynamic in behavior. I can't usually rely on there just being say 3 regions such as Menu, Navigation & content or such.

    I've figured out a good way to do this with Prism.

    I've started a community to hopefully provide a central place for persons to go disucss Design patterns.

    http://www.compositedevpatterns.com/

    (Just got a new server in to host it so it may be up and down the next couple of days.)

    If you have a chance, the Training (Prism) articles. Lesson 3 is how I build Dynamic Regions using Templates right now.

    If I can accomplish the same thing with MEF, I'm definitely going to give it a try.

    Thanks.

    ReplyDelete
  9. Great post! I have been reading about PRISM and MEF for a while now. This post is very helpful.

    ReplyDelete
  10. Excellent article!

    ReplyDelete
  11. Awesome article - thank you.

    ReplyDelete
  12. how to resolve error loading in mef when we have many extensibility to load
    thanks for your answers

    ReplyDelete
  13. All the reasons exist in ioc, for example Unity. Can't see any reason to switch to MEF from Unity.

    ReplyDelete
  14. I might learn to appreciate MEF, but I want to clarify a couple of things. Early on you mention it is not using Unity. In an exploration of my own, I learned that it was built around Unity, with all the DI container goodness that goes with it. Or has that changed since last time I checked?

    ReplyDelete
    Replies
    1. MEF is a completely separate engine from Unity.

      Delete
  15. Hi Jeremy,
    A very nice article.

    I myself have been using MEF from its inclusion in .NET 4.0, and as you have pointed out it is managable and extensible.
    I am planning to use the light version of MEF for Windows Phone (http://msdn.microsoft.com/en-us/library/jj635137.aspx).
    It will be slightly different than the usual MEF container I guess.

    Thanks


    ReplyDelete