Silverlight Hack

Silverlight & related .NET technologies

About Me

Welcome to Silverlighthack.com.  This is a site where you can find many articles on Silverlight, Windows Phone 7 and .NET related technologies.  

My name is Bart Czernicki.  I have been working with computers since 1988 and have over 12 professional years in the IT field focusing on architecture, technology strategy and product management.  I currently work as a Sr. Software Architect at a large software development company.

Below is the cover of my new book that shows how Silverlight's unique RIA features can be applied to create next-generation business intelligence (BI 2.0) applications.

Silverlight 4 Business Intelligence Soft 

Contact: [email protected]

View Bart Czernickis profile on LinkedIn

NONE of the comments or opinions expressed here should be considered ofmy past or current employer(s).  The code provided is as-is without anyguarantees or warranties.

Silverlight 2 (RC0 / RTM) - Dynamic Assembly Loading Fix

If you are utilizing the dynamic loading of assemblies (component based architecture inside Silverlight) in Beta 2, you will be in for a nasty surprise when upgrading to RC0.  Apparently, the way the Deployment class is utilized using a Singleton, it breaks some code you may have seen on several Microsoft blogs.

Specifically this line of code will fail with an InvalidOperationException ("Use the Current property to access the Deployment instance").  Below is a screen shot of Silverlight 2 RC0/RTM throwing a InvalidOperationException:

Deployment deploy = XamlReader.Load(appManifest) as Deployment;

So what can you do?  Luckily all the XamlReader load method does above is parse the AppManifest.xaml file and extract the deployment parts.  We can use LINQ to XML and do the parsing manually.

First, lets try to understand what we are doing.  The XAP package is a zip compressed file that includes our assemblies and configuration files.  One such file is the AppManifest.xaml.  In my case, I am utilizing Tim Heuer's dynamic loading example and the xap file we are downloading dynamically includes a AppManifest.xaml file that looks like this:

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="DynamicXapDataGrid_CS" EntryPointType="DynamicXapDataGrid_CS.App" RuntimeVersion="2.0.30523.6">
  <Deployment.Parts>
    <AssemblyPart x:Name="DynamicXapDataGrid_CS" Source="DynamicXapDataGrid_CS.dll" />
    <AssemblyPart x:Name="System.Windows.Controls.Data" Source="System.Windows.Controls.Data.dll" />
  </Deployment.Parts>
</Deployment>

This file is a manifest of what assemblies are included inside the package.  You can see above we downloading a xap package which includes 2 dlls (highlighted in bold above).  We simply need to get the string xaml and parse it using LINQ to XML.  Below is the code to do this:

IsolatedStorageFileStream fileStream = store.OpenFile("DynamicXapDataGrid_CS.xap", FileMode.Open, FileAccess.Read); StreamResourceInfo sri = new StreamResourceInfo(fileStream, "application/binary"); Stream manifestStream = Application.GetResourceStream(sri, new Uri("AppManifest.xaml", UriKind.Relative)).Stream; string appManifest = new StreamReader(manifestStream).ReadToEnd(); // remove this, doesn't work in RC0 / RTM//Deployment deploy = XamlReader.Load(appManifest) as Deployment; XElement deploymentRoot = XDocument.Parse(appManifest).Root; List deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements() select assemblyParts).ToList();Assembly asm = null;foreach (XElement xElement in deploymentParts){string source = xElement.Attribute("Source").Value;AssemblyPart asmPart = new AssemblyPart();fileStream = store.OpenFile("DynamicXapDataGrid_CS.xap", FileMode.Open, FileAccess.Read);StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(fileStream, "application/binary"), new Uri(source, UriKind.Relative));if (source == "DynamicXapDataGrid_CS.dll"){asm = asmPart.Load(streamInfo.Stream);}

Code overview:

  • Remove this line of code, this doesn't work anymore in Silverlight 2 RC0/RTM: Deployment deploy = XamlReader.Load(appManifest) as Deployment;
  • Next make sure you add a reference to the LINQ to XML namespace in order to be able to parse the AppManifest.xaml file
  • The following line of code loads the AppManifest.xaml file and extracts the 2 assembly names into a list.  Notice that all we want is the name of the assembly, which are found inside the AssemblyPart element inside the Source attribute.  You can do this outside of LINQ to XML and you can even write the code a little more expressively.
    • XElement deploymentRoot = XDocument.Parse(appManifest).Root; List deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
      select assemblyParts).ToList();
  • Now that we have our list of XElements we simply can iterate through them and extract the Source attribute:
    • foreach (XElement xElement in deploymentParts)
      {
      string source = xElement.Attribute("Source").Value;
  • The rest of the code is the same

In conclusion, the new Silverlight 2 RTM Deployment class utilizes a singleton which breaks the XamlReader.Load method.  In Beta 2, this code did the parsing for you.  Luckily with LINQ to XML, we can easily parse the data and extract the assembly information ourselves.

Posted: Sep 29 2008, 19:02 by Bart Czernicki | Comments (12) RSS comment feed |
  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Silverlight
Tags:
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us
blog comments powered by Disqus