This project has moved. For the latest updates, please go here.

Querying the CompositionContainer

The CompositionContainer exposes a handful of overloads to get exports and exported objects and collections of both.

You need to observe the following behavior shared among these methods overloads – unless noted otherwise.
  • When requesting a single instance, an exception will be thrown if none is found
  • When requesting a single instance, an exception will be thrown if more than one is found

GetExportedValue

In the following code snippet we request an instance of Root (contract) instance.
var container = new CompositionContainer(new AssemblyCatalog(typeof(Program).Assembly));
Root partInstance = container.GetExportedValue<Root>();
Dim container = New CompositionContainer(New AssemblyCatalog(GetType(Program).Assembly)) 
Dim partInstance As Root = container.GetExportedValue(Of Root)() 

If you have an export under a different contract name, you will need to use a different overload:

[Export("my_contract_name")]
public class Root
{
}

var container = new CompositionContainer(new AssemblyCatalog(typeof(Program).Assembly));
Root partInstance = container.GetExportedValue<Root>("my_contract_name");
<Export("my_contract_name")>
Public Class Root
End Class

Private container = New CompositionContainer(New AssemblyCatalog(GetType(Program).Assembly)) 
Private partInstance As Root = container.GetExportedValue(Of Root)("my_contract_name")

GetExport

GetExport retrieves a lazily instantiated reference to an export. Accessing the Value property of the export will either force the export instance to be created. Successive invocation of the export's Value will return the same instance, regardless of whether the part has a Shared or Non-Shared lifetime.

Lazy<Root> export = container.GetExport<Root>();
var root = export.Value; //create the instance.
Dim export As Lazy(Of Root) = container.GetExport(Of Root)() 
Dim root = export.Value 'create the instance. 

GetExportedValueOrDefault

GetExportedValueOrDefault works exactly as GetExportedValue with the difference that it won’t throw an exception in case nothing matches.

var root = container.GetExportedValueOrDefault<Root>(); // may return null

Dim root = container.GetExportedValueOrDefault(Of Root)() ' may return null

Last edited Aug 9, 2010 at 5:32 PM by haveriss, version 6

Comments

nichardrixon May 29, 2012 at 11:12 AM 
Can someone describe to me a situation where a class other than the composition root needs to query the container? If I had a standard IoC container and was passing it around my application I'd be sorely tempted to assert that I've made a big mistake in my software architecture..

gunungmerapi Feb 16, 2011 at 11:23 PM 
For some reason this does not work in Prism. I'm using ServiceLocator.Current static class property to get at the container instance in Prism.

gunungmerapi Feb 16, 2011 at 5:02 AM 
Are there any other ways to get at the container in prism? Can I use the IServiceLocator to do this - I've seen some people say this is possible but found not code or rationale within the documentation on how to accomplish this.

aL3891 Oct 26, 2009 at 2:29 PM 
can you make a query using meta data? i have a scenario where there are multiple repositories and i want to get the one with the metadata name x that ive defined in some settings i have.

nblumhardt Aug 5, 2009 at 8:06 PM 
@uriq yes - querying the container should be minimised. Sometimes it is necessary, but these situations should be the exception rather than the rule!

urig Jun 10, 2009 at 5:37 PM 
Just as a test of my understanding - doesn't querying the CompisitonContainer somewhat defeat the purpose of using MEF? Isn't having MEF match Imports and Exports transparently the "killer feature" for the framework? :)

jbe2277 May 23, 2009 at 10:07 PM 
When you need to use the container in a class that hasn’t created the container you need a way to retrieve the container object. I struggled with this scenario for quite some time and so I thought I might share my solution.


1. Register the container object

container = new CompositionContainer(catalog);
CompositionBatch batch = new CompositionBatch();
batch.AddExportedObject(container);
container.Compose(batch);


2. In the class that needs to use the container you can inject it

[ImportingConstructor]
public ApplicationController(CompositionContainer container, IShellView shellView)
{