tags:

views:

33

answers:

2

I have a MEF based solution that has several exported implementations of an interface.

What I want to be able to do is have a switch that removes ALL the current parts associated with the interface, and in their place, replace them with just a single implementation. I've been trying to do this with a CompositionBatch object, but it doesn't seem to work. Here's an example of what I'm doing:

[Export(typeof(IFoo)]
public class Foo1 : IFoo
{ }

[Export(typeof(IFoo)]
public class Foo2 : IFoo
{ }

I then have my container:

var container = new CompositionContainer(....);

which will now contain parts representing Foo1 and Foo2. What I want to do, is replace them with another IFoo implementation. This is what I'm trying, and I thought that this would work:

var partsToRemove
   = from part in container.Catalog.Parts
       from exDef in part.ExportDefinitions
       where exDef.ContractName == AttributedModelServices.GetContractName(typeof(IFoo))
     select part.CreatePart();

var batch = new CompositionBatch(null, partsToRemove);

batch.AddPart(new Foo3());

container.Compose(batch);

I'm expecting container.Catalog.Parts to change in order to reflect my changes, but it doesn't. It remains the same as when the container was first created.

What am I missing? Is this even the right approach? I've read Glenn Block's CodeBetter article on using ExportProviders, but he mentions that he'll write a part 2 in which he'll look at implementing a filtering ExportProvider (which may be closer to what I need to do).

+1  A: 

So CompositionBatch is about adding and removing explicit object instances and is not connected to the catalog, which is about adding a set of definitions (aka types if you will) that are then later constructed into object instances in the CatalogExportProvider. To do what you want you will need to actually filter to catalog before you pass it to the container to exclude the types you want. (See http://mef.codeplex.com/wikipage?title=Filtering%20Catalogs for an example of a filtering catalog).

Then if you want to add an explicit Foo instance you can use a CompositionBatch for that.

Wes Haggard
@Wes - Works a treat, thanks Wes.
Tim Roberts
A: 

Tim, are you expecting to do this dynamically at runtime after the container is created i.e. after the container has already composed some parts? Or are you trying to simply apply a filter at startup time?

Glenn Block
It would be at startup. So during startup I'm looking to replace all the found implementations of IFoo with a single DebugFoo (that obviously implements IFoo). I'm trying to avoid having to mess around with the catalogs that have been used (or even removing assemblies), and perform this replacement through a [Conditional] method.
Tim Roberts
Are you using a decorator to wrap them?
Glenn Block