Dynamic Part Instantiation in MEF
Disclaimer: This functionality is not shipping in .NET 4 (but is available in the recent CodePlex drops, see below for more details.)
The golden rule of using composition to simplify your architecture is to avoid calling the container directly.
Until now, MEF users have had to jump through hoops to observe this rule in some circumstances. The most common of these is dynamic part creation – creating instances of parts on-the-fly in response to application events.
To alleviate this, the latest Silverlight version of MEF in “Preview 7” introduces aDeclarative Context Adaptercalled PartCreator<T> .
Imagine we’re writing a pluggable text editor. The application uses a part to represent the document being edited:
- Every time OnNewDocument() executes, a new instance supporting IDocument is created (in this case the actual object will be of type TextDocument, )
- When MEF sees an [Import] attribute on a member of type PartCreator<T> , it will use the same rules as for Lazy<T> to determine the appropriate contract,
- The parameter T is the type of the exported value, not the type of the underlying part implementation,
- The return value from CreatePart() is a wrapper class, PartLifetimeContext<T> , that implements IDisposable and must be used to clean up the part when it is no longer required,
- PartLifetimeContext<T> has a property Value of type T, in this case T will be IDocument.
MEF supports PartCreator<T> implicitly, in a very similar way to Lazy<T>. There is no additional code required to get this behaviour.
Many scenarios for dynamic instantiation need to select the appropriate part to instantiate from several different implementations.
In this example, imagine we’re building a simple MVC web framework (don’t confuse this with ASP.NET MVC; this is just a made-up exercise, not a serious MVC framework design.)
Developers create controllers to handle the various URLs that the web application responds to. Each controller exports the IController contract, and adds some metadata describing the route that the controller handles.
Here’s part of the controller for the /home page:
To do this, the RequestHandler part imports an array of PartCreator<IController, IControllerMetadata> .
When a request comes in (see the HandleRequest() method) the appropriate part creator is chosen and used to create a controller:
Emulating PartCreator<T> on .NET 4
PartCreator<T> is not included in the .NET 4 builds of MEF – it was developed as part of the Silverlight MEF support (where CompositionContainer is much less accessible.) However, with a little work it is possible to emulate some of the PartCreator<T> functionality.
Included with the .NET beta-compatible version of MEF is a sample that supports a limited subset of the feature, under Microsoft.ComponentModel.Composition.DynamicInstantiation.
This assembly includes versions of the part creator types, and an ExportProvider that handles requests for PartCreator<T> when added to the container.
This sample doesn’t fully support all container features, and (as you can tell by the lack of unit tests) may blow up in unexpected ways. Instantiation performance is also not guaranteed, thanks to O(n^2) time complexity on the number of exporters of the contract being instantiated.
We’re including this so that .NET 4 users can experiment with the part creator APIs; it is not yet recommended for production use.