Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MEF = may experience frustration?

UPDATE

As I've tried to get MEF working throughout my application, I'm coming across more an more places where I just don't get why it's not automatically creating my library when I expect it to. I think it all comes back to what Reed was saying about needing MEF to create everything. So right now, I have an XML reader class that needs to use my CandySettings, but even though its ICandySettings property has the [Import] attribute, it doesn't get imported. First I found out that [Import] doesn't work on statics, so I changed this. But after that it still didn't work. I think it's because I manually create the XML reader object, and what MEF wants me to do instead is to [Import] the XML reader... which means that I now have to have an interface for that as well.

It's almost like using IoC (or for MEF, at least), it's an all-or-nothing affair. You can't just arbitrarily use it here and there, because ultimately whatever class you want to inject properties into also needs to be created by MEF.

Please correct me if I am wrong!


Original post

Well, it's not THAT bad yet. :) But I do have questions after Reed has pointed me at MEF as a potential alternative to IoC (and so far it does look pretty good).

Consider the following model: alt text http://bit.ly/9W0sHt

As you can see, I have an App, and this app uses Plugins (whoops, missed that association!). Both the App and Plugins require usage of an object of type CandySettings, which is found in yet another assembly.

I first tried to use the ComposeParts method in MEF, but the only way I could get this to work was to do something like this in the plugin code.

var container = new CompositionContainer();
container.ComposeParts(this, new CandySettings());

But this doesn't make any sense, because why would I want to create the instance of CandySettings in the plugin? It should be in the App. But if I put it in the App code, then the Plugin doesn't magically figure out how to get at ICandySettings, even though I am using [Import] in the plugin, and [Export] in CandySettings. EDIT (probably because I should be calling ComposeParts() from the App and then passing it the plugin?)

The way I did it was to use MEF's DirectoryCatalog, because this allows the plugin, when constructed, to scan all of the assemblies in the current folder and automagically import everything that is marked with the [Import] attribute. So it looks like this, and potentially in every plugin:

var catalog = new DirectoryCatalog(".");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

This totally works great, but I can't help but think that this is not how MEF was intended to be used?

like image 428
Dave Avatar asked Apr 16 '10 18:04

Dave


1 Answers

The "trick" here is that you want to have MEF create your plugins for you.

The way you'll do this is to have your Application compose itself, with the Plugin types specified:

class PluginRepository
{
    [ImportMany(typeof(IPlugin))]
    IEnumerable<IPlugin> Plugins { get; set; }
}

If you do this, and have MEF Compose your "repository" class, MEF will construct the objects. It'll then automatically Compose those as it constructs them, so ICandySettings will get composed without any intervention for you.

You only need to manually "compose" an object if MEF isn't constructing it for you.

like image 69
Reed Copsey Avatar answered Oct 01 '22 20:10

Reed Copsey