Loading your catalog.xaml dynamically in Silverlight
When developing Silverlight applications in Prism it is sometimes nice to have the ability to have your catalog.xaml be a little bit more dynamic than the standard examples you see in the Prism guidance. I will show you an example that allow you to load your catalog.xaml file dynamically and thus giving you the ability to save in a database, IsolatedStorage, etc.
Lets first take a look at what a sample catalog.xaml file would look like:
<m:ModuleCatalog
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:m="clr-namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite">
<m:ModuleInfo ModuleName="Security"
ModuleType="Security.SecurityModule, Security, Version=1.0.0.0"
InitializationMode="OnDemand"
Ref="Security.xap"/>
<m:ModuleInfo ModuleName="Logging"
ModuleType="Logging.LoggingModule, Logging, Version=1.0.0.0"
InitializationMode="OnDemand"
Ref="Logging.xap"/>
</m:ModuleCatalog>
Typically this file is located in the main Silverlight application with a build action of ‘Content’. If we wanted to be able to modify this, we would have to make a change, build it, and then publish it to our hosting website.
Let’s look at our Bootstrapper.cs file that we use to configure Prism. We will be looking at the GetModuleCatalog method:
protected override IModuleCatalog GetModuleCatalog()
{
var catalog = ModuleCatalog.CreateFromXaml(new
Uri("catalog.xaml", UriKind.Relative));
return catalog;
}
The interface IModuleCatalog lives in the Microsoft.Practices.Composite.Modularity namespace.
Now lets see how we can change our code so that we can load the catalog dynamically. The following code shows a simple implementation for this:
protected override IModuleCatalog GetModuleCatalog()
{
var modules = @"<m:ModuleCatalog " +
"xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"" +
"xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"" +
"xmlns:sys=\"clr-namespace:System;assembly=mscorlib\"" +
"xmlns:m=\"clr-namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite\">" +
"<m:ModuleInfo ModuleName=\"Security\"" +
"ModuleType=\"Security.SecurityModule, Security, Version=1.0.0.0\"" +
"InitializationMode=\"OnDemand\"" +
"Ref=\"Security.xap\"/>" +
"<m:ModuleInfo ModuleName=\"Logging\"" +
"ModuleType=\"Logging.LoggingModule, Logging, Version=1.0.0.0\"" +
"InitializationMode=\"OnDemand\"" +
"Ref=\"Logging.xap\"/>";
var xamlStream = new MemoryStream();
Byte[] bytes = Encoding.UTF8.GetBytes(modules);
xamlStream.Write(bytes, 0, bytes.Length);
xamlStream.Position = 0;
var catalog = ModuleCatalog.CreateFromXaml(xamlStream);
xamlStream.Close();
return catalog;
}
For demonstration purposes, I am showing you the catalog string inline in the method. In production, you would have a WCF service that would return a string containing the catalog information and you would just need to get a stream from it.
This gives you a lot of flexibility for third vendors or just adding new logic to your own applications. You could now deploy your .xap files and then update a database or serverside configuration file that keeps track of the catalog information. You could make this be part of your startup sequence in your application and turn on or off certain modules based on your licensing or some other metric.
Hope this helps….





Matt-
How would you pull the catalog from an asynchronously-returned stream in GetModuleCatalog()? The Bootstrapper will call this method but not get a value. Would it be necessary to modify the Bootstrapper Run() code?