views:

2559

answers:

9

Has anyone worked much with Microsoft's Managed Extensibility Framework (MEF)? Kinda sounds like it's trying to be all things to all people - It's an add-in manager! It's duck typing! I'm wondering if anyone has an experience with it, positive or negative.

We're currently planning on using an generic IoC implementation ala MvcContrib for our next big project. Should we throw MEF in the mix?

+1  A: 

It's not an injection of control container. It's plug-in support framework.

Artem Tikhomirov
+1  A: 

I'd say given it's going to hang off of 'System' namespace in the .NET 4.0 Framework that you couldn't go too far wrong. It will be interesting to see how MEF evolves and what influence Hamilton Verissimo (Castle) has on the MEF's direction.

If it quacks like a duck, it just might be part of the current flock of IoC containers...

J Healy
+6  A: 

This post refers to the Managed Extensibility Framework Preview 2.

So, I had a run through MEF and wrote up a quick "Hello World", which is presented below. I gotta say it was totally easy to dive into and understand. The catalog system is great and makes extending MEF itself very straight forward. It's trivial to point it at a directory of addin assemblies and let it handle the rest. MEF's heritage ala Prism certainly shows through, but I think it would be odd if it didn't, given that both frameworks are about composition.

I think the thing that sticks in my craw the most is the "magic" of _container.Compose(). If you look in at the HelloMEF class, you'll see that the greetings field is never initialized by any of the code, which just feels funny. I think I prefer the way IoC containers work, where you explicitly ask the container to build an object for you. I wonder if some sort of "Nothing" or "Empty" generic initializer might be in order. i.e.

private IGreetings greetings = CompositionServices.Empty<IGreetings>();

That at least fills the object with "something" until such time as the container composition code runs to fill it with a real "something". I don't know - it smacks a little bit of Visual Basic's Empty or Nothing keywords, which I always disliked. If anyone else has some thoughts on this, I'd like to hear them. Maybe it's something I just need to get over. It is marked with a big fat [Import] attribute, so it's not like it's a complete mystery or anything.

Controlling object lifetime isn't obvious, but everything is a singleton by default unless you add a [CompositionOptions] attribute to the exported class. That let's you specify either Factory or Singleton. It would be nice to see Pooled added to this list at some point.

I'm not really clear on how the duck typing features work. It seems more like meta-data injection upon object creation rather than duck typing. And it looks like you can only add in one additional duck. But like I said, I'm not really clear on how these feature work just yet. Hopefully I can come back and fill this in later.

I think it would be a good idea to shadow copy the DLLs that are loaded by DirectoryPartCatalog. Right now the DLLs are locked once MEF gets a hold of them. This would also allow you to add a directory watcher and catch updated addins. That would be pretty sweet...

Finally, I'm worried about how trusted the addin DLLs are and how, or if, MEF will behave in a partial trust environment. I suspect applications using MEF will require full trust. It might also be prudent to load the addins up in their own AppDomain. I know it smacks a bit of System.AddIn, but it would allow very clear separation between user addins and system addins.

Okay - enough blathering. Here's Hello World in MEF and C#. Enjoy!

using System;
using System.ComponentModel.Composition;
using System.Reflection;

namespace HelloMEF
{
    public interface IGreetings
    {
        void Hello();
    }

    [Export(typeof(IGreetings))]
    public class Greetings : IGreetings
    {
        public void Hello()
        {
            Console.WriteLine("Hello world!");
        }
    }

    class HelloMEF : IDisposable
    {
        private readonly CompositionContainer _container;

        [Import(typeof(IGreetings))]
        private IGreetings greetings = null;

        public HelloMEF()
        {
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            _container = new CompositionContainer(catalog);
            var batch = new CompositionBatch();
            batch.AddPart(this);
            container.Compose(batch);

        }

        public void Run()
        {
            greetings.Hello();
        }

        public void Dispose()
        {
            _container.Dispose();
        }

        static void Main()
        {
            using (var helloMef = new HelloMEF())
                helloMef.Run();
        }
    }
}
Andy S
I've recently played with MEF preview 4, and they've cleaned up the code somewhat. AggregatingComposablePartCatalog is now just AggregateCatalog, etc. All around a big win IMHO
Orion Edwards
+2  A: 

Andy, I believe Glenn Block answers many of folks (natural) questions like these in this thread up on the MSDN MEF Forum:

Comparison of CompositionContainer with traditional IoC Containers .

To a degree, Artem's answer above is correct relative to the the primary intent behind MEF, which is extensibility and not composition. If you're primarily interested in composition, then use one of the other usual IoC suspects. If, on the otherhand, you are primarily concerned with extensibility, then the introduction of catalogs, parts, metadata tagging, duck typing, and delayed loading all make for some interesting possibilities. Also, Krzysztof Cwalina takes a shot here at explaining how MEF and System.Addins relate to one another.

J Healy
+20  A: 

We are not aiming for MEF to be an all-purpose IoC. The best way to think about the IoC aspects of MEF is an implementation detail. We use IoC as a pattern because it is a great way to address the problems we are looking to solve.

MEF is focused on extensibility. When you think of MEF look at it as an investment in taking our platform forward. Our future products and the platform will leverage MEF as a standard mechanism for adding extensibility. Third-party products and frameworks will also be able to leverage this same mechanism. The average "user" of MEF will author components that MEF will consume and will not be directly consuming MEF within their applications.

Imagine when you want to extend our platform in the future, you drop a dll in the bin folder and you are done. The MEF enabled app lights up with the new extension. That's the vision for MEF.

Glenn Block
+4  A: 

On Andy's question of security for extensions that MEF loads (sorry I don't have enough points yet :) ), the place to address this is in a Catalog. MEF catalogs are completely pluggable, so you can write a custom catalog that validates assembly keys, etc before loading. You could even use CAS if you so desired. We are looking at possibly providing hooks to allow you to do this without having to write a catalog. However, the source for the current catalogs is freely available. I suspect the minimum is someone (maybe on our team) will implement one and throw it in an extension/contrib project on CodePlex.

Glenn Block
+4  A: 

Duck typing won't ship in V1 though it is in the current drop. In a future drop we will replace it with a pluggable adapter mechanism where one could hook in a duck typing mechanism. The reason we looked at duck typing is to address versioning scenarios. With Duck Typing you can remove the shared references between exporters and importers, thus allowing multiple versions of a contract to live side by side.

Glenn Block
A: 

More detailed discussion on this in this post and the comments

http://mikehadlow.blogspot.com/2008/09/managed-extensibility-framework-why.html

Glenn Block
+1  A: 

Ayende also has a pretty good write up here: http://ayende.com/Blog/archive/2008/09/25/the-managed-extensibility-framework.aspx

Aaron Marten