I’ve spent copious amounts of time lately digging into Silverlight 4’s new Managed Extensibility Framework (MEF) and seem to find new uses for it every day. I love the fact that you can download a remote XAP file and import all of its exported parts with basically two lines of code:

DeploymentCatalog dc = new DeploymentCatalog("MoreWidgets.xap");

dc.DownloadAsync();

What’s missing, it seems, is a mechanism to dynamically discover the XAPs that are available on the server. If I’m using MEF to support a plug-in architecture, for example, I might want to drop a XAP containing a new plug-in into a folder on the server and have the plug-in automatically show up in my browser the next time the application runs.

MEF won’t do that on its own, but it will if you lend it a helping hand. After discussing various ways to do dynamic discovery in MEF with Jeremy Likness, I wrote a sample to demonstrate a technique based on passing InitParams to the Silverlight control. The technique is pretty simple.

You begin by modifying the ASPX file that hosts your Silverlight application. First, you add an empty InitParams <params> element to the <object> element that instantiates the Silverlight control, and you include an ID and a runat="server" attribute so you can manipulate the element from server-side code:

<param name="initParams" id="ip" runat="server" />

Next, you add the following C# code to the ASPX file:

private void Page_Load(object sender, EventArgs e)

{

    StringBuilder sb = new StringBuilder();

    DirectoryInfo di = new DirectoryInfo(Server.MapPath("ClientBin"));

    FileInfo[] files = di.GetFiles("*.xap");

       

    foreach (FileInfo file in files)

    {

        sb.Append(file.Name);

        sb.Append("=,");

    }

       

    ip.Attributes.Add("value", sb.ToString());

}

This little piece of code enumerates the XAP files in ClientBin and writes them to the <object> element as InitParams. The resulting <param> element might look like this:

<param id="ip" name="initParams" value="Widgets.xap=,MoreWidgets.xap=,YetMoreWidgets.xap=,"></param>

The final step is to add logic to your Silverlight app to process InitParams and turn each XAP file listed there into a DeploymentCatalog that begins downloading when the app starts up. Here’s how I did it:

AggregateCatalog catalog = new AggregateCatalog();

 

foreach (string uri in Application.Current.Host.InitParams.Keys)

{

    DeploymentCatalog dc = new DeploymentCatalog(uri);

    catalog.Catalogs.Add(dc);

    dc.DownloadAsync();

}

 

CompositionHost.Initialize(catalog);

CompositionInitializer.SatisfyImports(this);

In real life, you’d probably want to process DownloadCompleted events to make sure the XAPs are downloaded successfully. And, of course, you’ll need to have recomposition enabled on your imports so the new exports will show up as the downloads complete.