In the last episode we were examining a creative approach that the development team behind the CRM demo incorporated for connecting views to their Prism regions using a combination of custom attributes, attached behaviors, and the managed extensibility framework (MEF). One of the commenters was a little critical of the ‘magic’ behind MEF, and rightly so as many of us like being able to trace the exact line that code will go through as opposed to relying on the magic of composition to work everything out for us. Today we bring you one of those unexpected issues in which the ‘magic’ behind MEF is a little demystified as well as our creative solution to the problem.
Our Issue – MEF + Application Library Caching
As we are taking a modular approach to creating the CRM demo application, one of the decisions that we made early on was to utilize the caching found within Silverlight to help reduce download times and some of the overall bulk of the application. This is great for many scenarios and provides a better usability experience when done correctly, however in our case something was amiss.
Each time we were trying to load up new modules with caching enabled we were getting an error around missing dependencies. Of course we thought “How can it be, MEF resolves everything!”, expecting the magic behind the framework to deliver what the application was asking for since we were certain that all imports/exports were aligned and all references were correct when we left Visual Studio. As it turns out… they all were, everything in code was correct but MEF was having an issue of not properly recognizing cached dependencies and loading was failing. Never backing down from a challenge, our developers set out to solve this.
Manifesting a Solution
We knew already that the heart of the issue is dependencies failing to load, so we needed to figure out some method for determining what dependencies were required before MEF looks, and fails, to load cached and/or required dependencies. Thankfully Silverlight provides this information for us within the AppManifest.xaml file that is packaged up within each Xap. I opened up the Contacts module so you can see what one of these looks like:
Exciting, I know. :) But excitement of xaml extensionpart listings aside, we now have the list of requirements that are needed for MEF to work its magic, but contained within the Xap this is destined to fail. Our high-tech solution? Post-build, process the following event on each module to copy the AppManifest.xaml over to the ClientBin directory:
xcopy "$(TargetDir)*.xaml" "$(ProjectDir)..\CRM.Web\ClientBin\$(TargetName)" /s /y /i /r
Step one complete, we know what dependencies are needed, now we just need to fulfill them somehow.
ApplicationNavigator Leads to DependenciesEnsurer
Working within the same line of thought behind the Infrastructure project, the core application provides us with a spot to manage and maintain some key functionality related to the state and overall maintenance of the application. One way of looking at these two is that if something is required to be shared among modules, like classes, styles, and resources, you should place it within the infrastructure, but if it meets some core application requirement, like module loading or perhaps ensuring dependencies load, place that within the core of the application. This way there is a logical breakdown of what goes into which project, but regardless of how you structure these things modules will have their requirements taken care of by some central location. I know in some cases developers and teams will create something of a .Core project/library as well which they can use to replicate similar functionality easily in different solutions – whatever works for you and your team is the best case scenario, no one of these solutions will apply 100% of the time.
Back on track, as you already guessed from the section heading we are using a class named ApplicationNavigator to handle navigation activities in the overall application – in our case, loading modules. Before diving into the LoadModuleAsync method, there are three methods I won’t dig into here but require a quick mention so you know they exist:
While these perform important functions in their own respect, the meat of the class is found in LoadModuleAsync:
uri, Action callback)
EventHandler<LoadModuleCompletedEventArgs> onModuleLoaded =
(s, e) =>
.ModuleManager.LoadModuleCompleted -= onModuleLoaded;
.ModuleManager.LoadModuleCompleted += onModuleLoaded;
var dependencyEnsurer =
EventHandler<EventArgs> onDependenciesEnsured =
dependencyEnsurer.EnsureProcessFinished -= onDependenciesEnsured;
dependencyEnsurer.EnsureProcessFinished += onDependenciesEnsured;
.ModuleCatalog.Modules.Single(m => m.ModuleName == uri).Ref);
Stepping through code, we first check if the module is loaded. It not, which is the default case since every module needs to load at some point, we set up an event and callback for adding the loaded module to out catalog and then utilize the DependenciesEnsurer (aptly named) to perform our download operations, handled in the RunEnsureProcessAsync method.
DependenciesEnsurer Leads to SynchronousDownloader
Beginning where we left off, RunEnsureProcessAsync is our entry point into DependenciesEnsurer:
.pathToXap = pathToXap;
var worker =
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.DoWork += worker_DoWork;
This doesn’t look that exciting, lets see what the BackgroundWorker is doing to get a better idea of the magic at hand here:
sender, DoWorkEventArgs e)
manifestString = SynchronousDownloader.DownloadString(
XDocument xDoc = XDocument.Parse(manifestString);
var fileNames = xDoc.Descendants().Where(xElement => xElement.Name.LocalName.Equals(
)).Select(xElement => xElement.LastAttribute.Value).ToList();
Now it’s making a little more sense… Remember those AppManifest files from before? We’re now parsing through via linq-to-xml, putting those into a list of file names, and running LoadExternalParts on that list:
//if (loadedAssemblyNamesCache.Contains(fileName.Replace(".zip", ""))) continue;
Stream fileStream = SynchronousDownloader.DownloadFile(
var assemblyStream = Application.GetResourceStream(
"application / binary"
var part =
var loadedAssembly = part.Load(assemblyStream);
Taking each file from the list, we check against an AssemblyCache (you can see refactoring in action there as the loadedAssemblyNamesCache has moved from a local reference to the AssemblyCache class) and if it hasn’t been loaded we utilize the SynchronousDownloader to download the file. When all is said and done the worker fires off EnsureProcessFinished and the callback to load this module eventually fires. Now that’s magic!
Next week we've got something special lined up that rhymes with "we're dropping some code" - I'll let our astute readers guess what that might mean. In preparation for that, ensure you've got SQL Server Express R2 or any compatible version installed to be sure that our database, humble as it may be right now, will work on your system. Now, we're not guaranteeing you'll be able to load it up and F5 into the CRM (we'll see what the next week brings), but you will be able to pour some code to see the progress we've made. I know I'm definitely excited!
Evan Hutnick works as a Developer Evangelist for Telerik specializing in Silverlight and WPF in addition to being a Microsoft MVP for Silverlight. After years as a development enthusiast in .Net technologies, he has been able to excel in XAML development helping to provide samples and expertise in these cutting edge technologies. You can find him on Twitter @EvanHutnick.
Copyright © 2002-2016 Telerik. All rights reserved.
Powered by Telerik