Partilhar via


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> .

image

PartCreator<T>

Imagine we’re writing a pluggable text editor. The application uses a part to represent the document being edited:

image Whenever the user clicks the ‘New’ button, the editor window creates a new instance:

image There are a few important things to notice here:

  • 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.

PartCreator<T, TMetadata>

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:

image Down in the plumbing of our MVC framework, the request handler is going to have to decide which of the available controllers will be invoked by an incoming request.

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:

image Notice that the controller variable is used in a using block. This ensures that the controller and any other resources that were used to construct it will be cleaned up after the request is handled.

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.

image

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.

Comments

  • Anonymous
    August 27, 2009
    hm.. so does this mean that the .net4 has become outdated before its even released? :/

  • Anonymous
    August 28, 2009
    @aL, .NET 4 is stabilising, while PartCreator<T> is targeting a future version and thus has time to evolve and mature if it needs to. Having a window into the future of MEF is A Good Thing (TM) - a project without a "v.Next" in the works is a dead project IMHO. Nick

  • Anonymous
    September 08, 2009
    I'm really looking forward to see this feature in production quality. At the moment I'm one of the developers who is using the container directly for dynamic part creation. MEF is great to wire the View with the ViewModel within the MVVM pattern together (WPF). See also: http://waf.codeplex.com

  • Anonymous
    September 13, 2009
    im not saying its a bad thing or that it shouldnt be a v.next, but what about v.present? what about updating some of those updated docs and samples on the codeplex site? learning and integrating mef is pretty difficult right now because there isnt a consistent documentation and the api keeps moving.. where does v1 end and v2 start? thats what i mean be .ne4 beeing outdated before it ships.. and what's the ssituation moving from v1 to v2? is v2 addative? will be not reference the v1 assemblies in the gac at all?

  • Anonymous
    September 13, 2009
    that should say "outdated docs/samples"