views:

276

answers:

1

In my last application, using MEF to load plugins went just fine, but now I'm running into a new issue. I have a solution for it that I explain at the end of this question, but I'm looking for other ways to do it.

Let's say I have an interface called ApplianceInterface. I also have two plugins that inherit from ApplianceInterface, let's call them Blender and Processor. Now, I would like to have multiple Blenders and Processors in my application, but I am not sure how to instantiate them properly.

Before, I would simply use the ImportMany attribute and upon calling ComposeParts, my application would load Blender and Processor. For example:

[ImportMany(typeof(ApplianceInterface))]
private IEnumerable<ApplianceInterface> Appliances { get; set; }

and my Blender and Processor plugins would be attributed like this:

[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(MyInterface)]
public class Blender : ApplianceInterface
{
    ...
}

but what this ends up doing for me is populating Appliances with one Blender and one Processor. I need to be able to create an arbitrary number of Blender and Processor objects.

Now, from the documentation I understand that [PartCreationPolicy(CreationPolicy.NonShared)] is what allows MEF to create a new instance each time, but is there a similar "magical" way to create a specific number of instances of something using MEF? Up until now, I've relied on [Import] and [ImportMany] to resolve the assemblies.

Is my only option to use a global container, and then resolve the export manually using GetExportedValue<>? I have tried GetExportedValue<> and that implementation does work fine for me, but I was just curious if there is a better, more accepted way to do it.

UPDATE

I just realized a big mistake, and GetExportedValue<> isn't what I really want. I'm iterating over an IEnumerable, and when I get a match (based on some parameters), I want to instantiate a new object of the current value. GetExportedValue<> ends up failing in the case where I have two different plugins that both export ApplianceInterface.

I think my question is different now, and is probably a C# specific one.

+2  A: 

ExportFactory is what you are looking for, but it is currently only available in Silverlight. Here is a question that explains how to handle this on the desktop: http://stackoverflow.com/questions/2878265/multiple-instances-of-a-single-mef-dll

Daniel Plaisted
Thanks, that's an interesting approach. So use MEF to resolve a single instance of a class factory which can then create multiple instances of a specific type. I think it would work fine, but does require more implementation that simply calling GetExportedValue.My appliance creation all occurs in a single object that manages all of the appliances in the kitchen, so the MEF container is only needed in that one assembly. However, if things change and I need to resolve elsewhere, I think your suggestion is definitely the way to go.
Dave
It looks like this works for my question before I realized a fundamental flaw in my thinking (or lack thereof). I could possibly extend it to handle my new issue as well, but it's not the best solution. When I have two ApplianceInterfaces, I could pass a string to the class factory to get a specific type of ApplianceInterface, because there could be multiple plugins that expose this interface, yet I need to be able to create an instance of the derived class. There's got to be a way to do this with C# magic but I haven't figured it out yet.
Dave