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.
On Jun 17 2010 4:03 AMBy jprosise
Great idea! Thanks for the post!
PingBack from http://topsy.com/www.wintellect.com/CS/blogs/jprosise/archive/2010/06/17/dynamic-xap-discovery-with-silverlight-mef.aspx?utm_source=pingback&utm_campaign=L2
Why not set up a database with xap's? This way you can regiseter new modules from an admin UI. Just a thought.
This is a very good idea, but it only works for in browser applications.
OOB apps don't have init parameters, so a different solution would be needed.
We currently use a file that gets included with the XAP, and pull configuration from there. However, while this can still do what you're advocating, you will need additional libraries to modify the file in the XAP and replace it(some zip utils).
Nice approach. An alternative approach which allows more real-time scanning is to use a WCF service on the server which scans the client bin. You can then use a background thread to watch for notifications / use SL duplex polling.
I put together a demo of this for my MIX talk (http://live.visitmix.com/MIX10/Sessions/CL52) though that particular version didn't work live :-) ). The working code is here: http://cid-f8b2fd72406fb218.skydrive.live.com/self.aspx/blog/MIX%202010%20Demos.zip in the MefDemo_Extensible samplle. It uses a background thread just for illustration.
Great comments! Yes, there are lots of ways to crack this nut, including services and config files. The duplex approach is cool because the user wouldn't have to restart the app to have a new plug-in show up; it would just appear. Only problem I see with duplex is that it limits scalability, but most of us aren't trying to serve 100,000 concurrent clients anyway.
Great post , but how about the silverlight navigation applications? Is there anyway to use MEF to dynamically a zap wher certain URL is passed into browser
You've been kicked (a good thing) - Trackback from DotNetKicks.com