Silverlight how to: On-demand assembly deployment
March 14, 2008 @ 10:44 am in Microsoft, Silverlight
One of the cool new features of Silverlight 2 is the concept of on-demand deployment of assemblies. In most interactive development there is a desire to minimize the amount of data a user has to download to get your RIA up and running. The application package (XAP) size can grow quite quickly if one tries to include all of resources required to run the entire application. In Silverlight 2 we have the concept of a XAP file or compressed package (zip file). By default, the XAP contains an application assembly and any Silverlight assemblies that your application is dependent on (System.Xml.Linq, etc). In Silverlight 2 we have the ability to generate more than one XAP file giving us the opportunity to deploy additional assemblies on demand, asynchronously to the initial payload.
To leverage this technology one has to understand the concept of “AssemblyParts” and how reflection is used to extract an assembly from a downloaded XAP. The following example will show how one can code this functionality in Silverlight 2 Beta 1.
The first step in downloading an additional assembly is to go and get the XAP package. Note the use of a BaseAddress. In my example the base address is http://localhost/MultipleXap_Web/.
1 2 3 4 5 | Uri addressUri = new Uri(_baseUri, "ClientBin/MultipleXap1.xap"); System.Net.WebClient wcXap1 = new System.Net.WebClient(); wcXap1.BaseAddress = _baseUri; wcXap1.OpenReadCompleted += new OpenReadCompletedEventHandler(wcXap1_OpenReadCompleted); wcXap1.OpenReadAsync(addressUri); |
Once downloaded, the “OpenReadCompleted” event will fire and one can extract the assembly from the XAP. I have chosen to factor into a method the logic used extract the Assembly from the compressed zip file. In the event that we had multiple assemblies we could use Linq to navigate the xml of AppManifest and programmatically load each assembly.
1 2 3 4 5 6 7 8 9 10 | public Assembly LoadAssemblyFromXap(string relativeUriString, Stream xapPackageStream)
{
Uri uri = new Uri(relativeUriString, UriKind.Relative);
StreamResourceInfo xapPackageSri = new StreamResourceInfo(xapPackageStream, null);
StreamResourceInfo assemblySri = Application.GetResourceStream(xapPackageSri, uri);
AssemblyPart assemblyPart = new AssemblyPart();
Assembly a = assemblyPart.Load(assemblySri.Stream);
return a;
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | void wcXap1_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if ((e.Error == null) && (e.Cancelled == false))
{
// Convert the downloaded stream into an assembly
Assembly a = LoadAssemblyFromXap("MultipleXap1.dll", e.Result);
/****************************************************************
* The following should work since I did the following
*
* "added a reference to second assembly then specified that
* the library assembly that is referenced by the application
* project is not included with the application package
* when the application assembly is built"
*
* This syntax compiles, but DOES NOT run correctly
****************************************************************
* MultipleXap1.Page page = new MultipleXap1.Page();
********************************************************/
object page = a.CreateInstance("MultipleXap1.Page");
//Insert UserControl into the Primary grid.
this.LayoutRoot.Children.Add(page as UserControl);
}
} |
Once the assembly has been extracted, we can create an instance of the selected UserControl by using the “CreateInstance” method on the Assembly object. Based on Microsoft’s documentation, we should have been able to add a project reference to the on-demand XAP, within our default Silverlight Application. This would give us access to that second assemblies types. We can make the reference and the project compiles, but throws an exception at runtime. CreateInstance is not a preferred approach since it drastically limits how we can leverage the strong typing of objects instantiated from this reflected assembly.
Code: MultipleXap.zip

Tagged as 

March 15th, 2008 at 1:25 am
Great article! BTW: You should be able to avoid using CreateInstance and get back strong object typing by moving your MultipleXap1.Page instantiation code into a separate method then call that method from the OpenReadComplete event handler. Not exactly sure why you can’t new up the Page object from within the event handler, but moving it out appears to solve the problem. Hope this helps.
April 7th, 2008 at 11:08 am
I see no much difference from MS example…
June 21st, 2008 at 7:44 am
Thanks for this. I had code I was using in SilverlightDesktop.net that loading the .dll but that required you to remove the .dll from the .xap each time and manually put it in the /bin directory. I gave you credit in the next release of SilverlightDesktop.net.
August 12th, 2008 at 11:58 am
I’m worried about security for these on-demand assemblies. Let’s say I had a proprietary algorithm that was a trade secret, e.g. elevator management algorithms.
I want to create a safe way to use those algorithms in my Silverlight application. Let’s say I want to show my elevators opening and closing on the 1st floor using my algorithm to decide when those doors would open and close.
Originally I thought I could take me elevator.dll that currently exists and reference it in Silverlight. But now I understand that they would use different CLR’s and therefore can share code but not references.
So I’ll have to copy my code into a Silverlight on-demand library. Is there any way an unscrupulous competitor could get my DLL?
This on-demand loading would mean that it’s would only be in memory, right? So there would be no DLL on the hard drive to grab. So what are the chances it could be inspected and stolen that way.
Do you have any ideas for solving this problem?
August 18th, 2008 at 4:56 am
what if my main xap file contains a referenced assembly that I want to inspect via reflection. How does one go about this without re-downloading the xap file into a stream?
ie:MultipleXap1 was not a silverlight application with a xap output, but a plain silverlight assembly.
August 27th, 2008 at 9:26 pm
@MKelsey - The solution is don’t put your algorithm on the client. It doesn’t matter how you package it or download it. If you run the algorithm in Silverlight, on the client, then it has to be sent to the client. If someone wants it enough, they will be able to get it. The solution to your problem would be to run the code on the server via an Ajax call of some sort.