Silverlight 4, MEF and the DeploymentCatalog ( again :-) )

The Silverlight 4 beta came with a version of MEF that had 3 catalogs – namely AssemblyCatalog, TypeCatalog and AggregateCatalog. They’re pretty easy to understand and I made a screencast on the topic here.

The Silverlight 4 preview toolkit came with a PackageCatalog that is really useful as it works with another class Package to download separate XAP files and expose their exported components to MEF.

The new MEF drop on codeplex has an evolution of those classes called the DeploymentCatalog. I wrote about it here and here.

It’s really easy to use but when I encountered the PackageCatalog I felt like I wanted something “bigger” and wrote a bit of code back here that wrapped up the PackageCatalog into a component that knew how to download not just one additional package but a number of them.

I wanted to do a similar thing with the DeploymentCatalog and so I put together a few simple classes to let me do that. Here’s a resource from an app.xaml file showing how the classes that I knocked up might be used;

  <Application.Resources>
    <ldr:DeploymentCatalogLoader x:Key="loader" 
      ConfigLoaded="OnConfigLoaded"
      ConfigGroupLoaded="OnConfigGroupLoaded"
      ConfigItemLoaded="OnConfigItemLoaded">
      <cfg:DeploymentCatalogConfig>
        <cfg:DeploymentCatalogConfigGroup>
          <cfg:DeploymentCatalogConfigItem 
            Uri="NotepadPlugin.xap" />
          <cfg:DeploymentCatalogConfigItem
            Uri="ClockPlugin.xap" />
        </cfg:DeploymentCatalogConfigGroup>
      </cfg:DeploymentCatalogConfig>
    </ldr:DeploymentCatalogLoader>
  </Application.Resources>

and it’s defining;

  • a loader
  • a configuration for the loader to load
  • a single group within that configuration
  • 2 XAPs to load within that group
    • NotepladPlugin.xap
    • ClockPlugin.xap

and then I can just grab that loader that’s the resource and tell it to load itself as in this code here taken from some app startup routine;

    DeploymentCatalogLoader loader =
        this.Resources["loader"] as DeploymentCatalogLoader;

      if (loader != null)
      {
        CompositionHost.Initialize(loader.LoadCatalogConfigAsync());
      }

and that’s it.

The loader will pull down the XAPs in group order and add them into its own aggregate catalog and so things “just work”. The container is returned from the call to LoadCatalogConfigAsync and so you can then do whatever you like with it ( I use it to initialize the CompositionHost here ).

If I wanted to take more control of the CompositionContainer that’s being used here then there’s a few more overloads on my LoadCatalogConfigAsync method so I can do something like;

      DeploymentCatalogLoader loader =
        this.Resources["loader"] as DeploymentCatalogLoader;

      if (loader != null)
      {
        TypeCatalog typeCatalog = new TypeCatalog();

        CompositionHost.Initialize(
          loader.LoadCatalogConfigAsync(typeCatalog));
      }

Note – that’s just an example because I don’t actually put anything into the TypeCatalog.

It wouldn’t be too tricky to take that XAML based configuration and move it to a separate file outside of the app altogether and then download that file using WebClient at runtime.

I used these classes to build a simple example which is embedded in the page below.

That application starts off life with no plugins loaded and then dynamically pulls in the 2 little plug-ins for a notepad editor and a clock. You can click the Windows icon to full screen it.

The source code for this is here, it’s fairly rough and ready but it might be a starting point for something you’re doing.