Any extension which downloads modules

Topics: Prism v4 - WPF 4
Nov 23, 2011 at 8:37 PM
Edited Nov 23, 2011 at 8:54 PM

from a repo before registering

 

also how about updating modules before loading - either auto or on demand / user consent ?

 

Developer
Nov 24, 2011 at 1:03 PM

Hi,

You might find the following section from the Modularity Chapter in the Prism MSDN documentation useful to your purposes:

Downloading Remote Modules in the Background

The aforementioned section, however, is targeted at Silverlight. For WPF applications, the scenario of remote module downloading is not supported out of the box. Below you will find an explanation of the way Prism loads modules, which might be useful in case you want to create an extension that supports downloading remote modules in WPF applications.

Once a module has been loaded into the module catalog, it is represented through a ModuleInfo instance. This instance, however, does not contain the bytes of the module's assembly, but rather a description of the module: it's name (ModuleName), the type of the class implementing IModule inside the project (ModuleType), the initialization mode (InitializationMode), the state (State), dependent modules (DependsOn), and a reference to the location of the module's assembly (Ref). The latter will be of interest to us in regards to where to download the module from.

When you indicate that you wish to load a module, a module type loader (which must implement the IModuleTypeLoader interface) retrieves the assembly from the Ref property of the ModuleInfo, loads it in memory, and then creates a new instance of the class that implements IModule in your project (i.e. the one described in the ModuleType property), and calls its Initialize method.

The Silverlight Prism Library provides a XapModuleTypeLoader (or MefXapModuleTypeLoader, in case you're using MEF), which uses a FileDownloader to download the XAP package containing your module(s). The FileDownloader is basically a wrapper for the WebClient class in Silverlight.

The WPF Prism Library, on the other hand, provides a FileModuleTypeLoader (or MefFileModuleTypeLoader, in case you're using MEF), which simply retrieves your module's assembly from the directory specified in the Ref property. The value of the Ref property must look like this "file://c:/MyProject/Modules/MyModule.dll" in order for this type loader to retrieve it correctly. To do this, the FileModuleTypeLoader (Prism.Desktop/Modularity/FileModuleTypeLoader.Desktop.cs) relies on an AssemblyResolver (Prism.Desktop/Modularity/AssemblyResolver.Desktop.cs), which provides a LoadAssemblyFrom method that loads in memory the assembly in the path specified.

One possible approach you could follow would be to create a WPF file downloader (which could be named WPFFileDownloader) that uses a WebClient to download your assembly from a remote location and store it on a folder (which could be named AlreadyDownloadedModules). Then you could create a custom module type loader (which could be named WPFRemoteFileModuleTypeLoader) which uses this WPFFileDownloader to retrieve the assembly (if it's not already present in the AlreadyDownloadedModules folder), and then use the AssemblyResolver to load it in memory. You can reuse most of the code in the FileModuleTypeLoader/MefFileModuleTypeLoader class to avoid writing it yourself; basically you should modify the LoadModuleType method to use remote loading, and modify the CanLoadModuleType method to indicate that this module loader can load ModuleInfo's whose Ref property points to a remote Uri.

This should make the remote loading optional; which could be an interesting opportunity to reuse the WPFFileDownloader on a separate component whose only responsibility is to prompt for updates and update the modules in the AlreadyDownloadedModules folder if necessary.

Once you have created your custom module loader, you should create a custom ModuleManager that simply inherits from the default one, but overriding its ModuleTypeLoaders property to include the WPFRemoteFileModuleTypeLoader in the list. Then you should add your custom ModuleManager to the container (exporting it with the IModuleManager interface as the contract type) so that it replaces the default one.

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Dec 20, 2011 at 8:23 PM

Thanks Guido

Is there any extensibility point to get the list of modules to load from a web service, based on params such as user, machine etc ?

 

Developer
Dec 21, 2011 at 5:26 PM

Hi,

The implementations details for this functionality will depend mostly of your personal preferences and the requirements of your scenario.

As far as I know, Prism does not provide this functionality out of the box. However, you might find the following blog post by Guido Maliandi useful:

In the aforementioned blog post, the sample application provided uses a service (the IAuthorizationService) to obtain a list of modules depending of a parameter (the role of the user) and then, load the modules specified in this list through the Prism's ModuleManager. This approach might be similar to the functionality you are describing.

Also, you might find more information about extending Prism in the following chapter of the documentation:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Dec 22, 2011 at 8:08 PM

Thanks Damian, that is great, will look into it

on another note, any idea on when is BootStrapper.Container initialized ?

Developer
Dec 23, 2011 at 5:10 PM

Hi,

You might find that Creating and Configuring the Container is a stage of the bootstrapping process, which is called by the Bootstrapper.Run method.
For more information regarding the sequence followed in the bootstrapping process and how a Prism application initializes, you might find the following chapter of the Prism documentation at MSDN useful:

Regards,

Agustin Adami
http://blogs.southworks.net/aadami