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();
}
}
}