views:

64

answers:

1

I am playing around with the new System.ComponentModel.Composition namespace in .NET 4.0 beta 2, also known as the Managed Extensibility Framework.

I use the following C# example where a Monkey imports a Banana:

public interface IBanana 
{ 
}

[Export(typeof(IBanana))]
public class Banana : IBanana 
{ 
} 

public class Monkey
{
    [Import(typeof(IBanana))]
    public IBanana Banana { get; set; }
}

However, when I try to compose the monkey as follows then I get an InvalidOperationException with the message "This object has not been initialized - the property 'SourceProvider' must be set.":

var exportProvider = new CatalogExportProvider(new TypeCatalog(typeof(Banana)));
var container = new CompositionContainer(exportProvider);
var monkey = new Monkey();
container.ComposeParts(monkey);

What am I missing here? I am aware that I can pass the catalog directly without wrapping it in a CatelogExportProvider, but shouldn't the above also work?

+1  A: 

The CatalogExportProvider needs a reference back to the container. The following code should work:

var exportProvider = new CatalogExportProvider(new TypeCatalog(typeof(Banana)));
var container = new CompositionContainer(exportProvider);
exportProvider.SourceProvider = container;
var monkey = new Monkey();
container.ComposeParts(monkey);

The container does this automatically when you pass a catalog into the constructor. I don't think there's often much of a reason to create the CatalogExportProvider manually.

The reason the CatalogExportProvider needs a reference to the container is that there may be parts in the catalog with imports that need to be satisfied by other export providers that the container is hooked up to.

Daniel Plaisted
I have come to the same conclusion by examining the System.Component.Composition.dll with reflector. As for the reason to create ExportProviders manually, this is necessary if you want to build a container that can fall back on defaults without complaining about multiple matching exports.
Wim Coenen