Recomposition

Some applications are designed to dynamically change at runtime. For example, a new extension may be downloaded, or others might become unavailable for a variety of reasons. MEF is prepared to handle these kinds of scenarios by relying on what we call recomposition, which is changing values of imports after the initial composition.

An import can inform MEF that it supports recomposition through the [System.ComponentModel.Composition.ImportAttribute] using the Allowrecomposition property. See the code snippet below:

[Export]
public class HttpServerHealthMonitor
{
    [ImportMany(AllowRecomposition=true)]
    public IMessageSender[] Senders { get; set; }
<Export()>
Public Class HttpServerHealthMonitor
    <ImportMany(AllowRecomposition:=True)> 
    Public Property Senders() As IMessageSender()

This tells MEF that your class is ready to handle recomposition, and if the availability of IMessageSender implementations changes (either a new one is available, or made unavailable), the collection should be changed to reflect it. Once a part has opted in for recomposition, it will get notified whenever there is a change to the implementations available in the catalog, or if instances have been manually added / removed from the container.

Caveats of Recomposition

  • When recomposition occurs, we will replace the instance of the collection / array with a new instance, we will not update the existing instance. In the example above, if a new IMessageSender appears, Senders will be completely replaced with a new array. This is in order to facilitate thread-safety.
  • Recomposition is valid for virtually all types of imports supported: fields, properties and collections, but it is not supported for constructor paramters.
  • If your type happens to implement the interface [System.ComponentModel.Composition.IPartImportsSatisifiedNotification], be aware that ImportCompleted will also be called whenever recomposition occurs.

Recomposition and Silverlight

In Silverlight Recomposition plays a special rule with regards to application partitioning. For more on that see the DeploymentCatalog topic.

Last edited Aug 9, 2010 at 6:31 PM by haveriss, version 7

Comments

davidgrenier Oct 6, 2010 at 4:37 PM 
Here's a monitoring implementation using Rx.NET:

var path = @"C:\Extensions\";
var fsw = new FileSystemWatcher(path, "*.dll") { EnableRaisingEvents = true };
var catalog = new DirectoryCatalog(path);

var fileChanges =
(from change in new [] {"Changed", "Created", "Deleted"}.ToObservable()
from e in Observable.FromEvent<FileSystemEventArgs>(fsw, change)
select new Unit())
.Merge(Observable.FromEvent<RenamedEventArgs>(fsw, "Renamed").Select(o => new Unit()))
.Sample(TimeSpan.FromSeconds(1));

var obs = fileChanges.Subscribe(o => catalog.Refresh());

fsw.WaitForChanged(WatcherChangeTypes.All);

//Don't forget to dispose your obs at application end.

kbrowns Aug 6, 2010 at 12:00 PM 
in the "Recomposition and Silverlight", I think you meant to say "plays a special ROLE" (not rule).

lancecontreras Jul 28, 2009 at 12:51 PM 
I think they removed the bool parameter that monitors changes in the directory, instead they put a Refresh method to the DirectoryCatalog to discover additional extensions in the folder, though you can write your own logic for watching directory and call the refresh method when the folder is modified.

Gutek Apr 7, 2009 at 11:39 AM 
Recomposition will work without DirectoryCatalog("dir", true")? as far as I understand, this is the only default catalog that is monitoring changes to load/unload new extenstions.