In continuation with my previous post, I would like to take dynamic loading to the next level.

Firstly, I would be replacing the download of the dynamic modules using Web Client with a service call.

The reason for this is simple, more flexibility and additional security. When using Web Client, our dynamic dll is placed alongside the xap in the client bin folder, thus making it publicly available via a static url. This posses a security risk for applications handling sensitive data. By using the web service, we can not only avoid the dynamic dll being hosted on the web but can also add additional security like a session token etc.

Next, I would be adding some versioning to the dynamic modules so that the client can cache the dynamic modules if necessary. The versioning not only enables client side caching but also enables any version rollback or parallel versioning.

Now that I have given some idea about what I would be doing in this post, let us take a look at the implementation in detail.

The web service will consist of two calls, the first which returns all the dynamic modules that are available and the other which will return the dynamic assembly itself.

The versioning takes place in two steps

  1. There is a EnableCache flag added to the application configuration. This helps to disable any caching of dynamic modules on the client side.
  2. The version attribute for that dynamic assembly. For this, I have maintained a simple Assemblies.xml file listing all the dynamic modules available

Here is the service code:

static string appData = AppDomain.CurrentDomain.BaseDirectory + “/App_Data/”;
public class AssemblyInformation
{

public string AssemblyName { get; set; }
public string Version { get; set; }
public bool IsNew { get; set; }

}
[OperationContract]
List<AssemblyInformation> GetAssemblies(List currentVersions)
{

if (currentVersions == null) throw new ArgumentNullException(“CurrentVersions”);
bool EnableCache = Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings[“EnableCache”]);
List assemblyVersions = new List();
XElement document = XDocument.Parse(File.ReadAllText(appData + “Assemblies.xml”)).Root;
IEnumerable<XElement> assemblies = document.Elements();
foreach (var assembly in assemblies)
{

string name = assembly.Attribute(“Name”).Value;
string version = assembly.Attribute(“Version”).Value;
string source = assembly.Attribute(“Source”).Value;

assemblyVersions.Add(new AssemblyInformation
{

AssemblyName = name,
Version = version,
IsNew = !EnableCache || !currentVersions.Any(v => v.AssemblyName == name) || currentVersions.FirstOrDefault(v => v.AssemblyName == name).Version != version

});

}
return assemblyVersions;

}

[OperationContract]
byte[] GetAssembly(string assemblyName)
{

if (string.IsNullOrWhiteSpace(assemblyName)) throw new ArgumentNullException(“assemblyName”);
List<AssemblyInformation> assemblyVersions = new List<AssemblyInformation>();
XElement document = XDocument.Parse(File.ReadAllText(appData + “Assemblies.xml”)).Root;
XElement assembly = document.Elements().FirstOrDefault(a => a.Attribute(“Name”).Value == assemblyName);
if (assembly == null) throw new FileNotFoundException(“Assembly ” + assembly + ” was not found”);

string source = assembly.Attribute(“Source”).Value;
return File.ReadAllBytes(appData + source);

}

When configuring the service make sure that you either increase the service timeout or enable dynamic compression. It is necessary in the case that the dynamic module is large and the

This is how the Assemblies.xml looks like

<Assemblies>

<Assembly Name=”SampleModule.SilverlightControl1″ Version=”1.0.0.0″ Source=”SampleModule.SilverlightControl1.dll” />

</Assemblies>

In the Silverlight client, depending on the IsNew flag on the list of assemblies, the client can download the required dynamic modules.

All the dynamic modules that have been downloaded can be stored in Isolated storage of the application along with its versions.

Following is a code snippet demonstating on how to save the assembly to the isolated storage and versions

private void SaveAssembly(AssemblyInformation assembly, byte[] data)
{

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{

string file = assembly.AssemblyName + “.dll”;
using (IsolatedStorageFileStream fileStream = store.OpenFile(file, FileMode.OpenOrCreate, FileAccess.ReadWrite))

fileStream.Write(data, 0, data.Length);

}

}

private void SaveVersions(List assemblies)
{

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{

using (IsolatedStorageFileStream stream = store.OpenFile(“Version.xml”, FileMode.Create, FileAccess.Write))
{

DataContractSerializer serializer = new DataContractSerializer(typeof(List));
XmlWriter writer = XmlWriter.Create(stream, null);
serializer.WriteObject(writer, assemblies);
writer.Flush();

}

}

}

One thing you must take care is that, the default quota for Isolated Storage is 1MB. This quota can be increased by requesting for more quota in an user instantiated event like button click. Take note that the user may decline your request for increase in storage quota.

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{

store.IncreaseQuotaTo(1024 * 1024 * 10);

}

Summarizing, I have added a service to load the required dynamic modules along with versioning. I have also optimized the performance by client side caching using Isolated storage.

Further Improvements

Well having come so far, we can still go a long way. here are somethings that can be done.

  • In place of just simple versions, the versioning scheme can also use a time stamp of the dynamic module to load a recent dynamic module. this can come in handy when you want to optionally provide updates to your modules on demand.
  • Create a control which takes the required assembly and type name to load that module for you. You can thus even give a design time loading so that you can preview your changes when you want without having to provide a new release.

In my future posts, I would be demonstrating how to navigate to a page contained in a dynamic assembly. Currently this is not supported in silverlight 4 and there is a very simple solution to this problem. So check back later for more on this and other topics.

Related Links

Advertisements

One thought on “Dynamic loading of Assemblies II

Share your thoughts

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s