Module OnDemand=true doesn't work

Topics: Prism v1
Jul 10, 2013 at 12:00 PM
Hi All,

I am using Prism 4.1 as my application framework. there are a couple of modules in my app, what i want is to load each module when it's needed. below are the main codesnippets of my app:

In Bootstrapper class:
    protected override void ConfigureAggregateCatalog()
    {
        base.ConfigureAggregateCatalog();

        this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));

        DirectoryCatalog catalog = new DirectoryCatalog("DirectoryModules");
        this.AggregateCatalog.Catalogs.Add(catalog);
    }
one module class:
[Module(ModuleName = "ModuleHouseOwnerInfo", OnDemand = true)]
public class ModuleHouseOwnerInfo : IModule
{
    [ImportingConstructor]
    public ModuleHouseOwnerInfo()
    {
    }
}
However, it seems to me that module attribute OnDemand = true doesn't work as expected, because I did see my ModuleHouseOwnerInfo.dll is loaded in memory when my app is loaded.

by the way, the ModuleHouseOwnerInfo.dll is output to folder DirectoryModules.

In addition, I don't want to use LoadModule API to load my module dynamically as I have a lot of modules in my app and i don't like to load each in code.

Anyone can help me on this? Any input will be much appreciated.
Developer
Jul 10, 2013 at 8:39 PM
Hi,

I believe this is due to how the DirectoryModuleCatalog works. Starting a module in Prism is divided in two steps: loading the assembly contained the module (if it was not loaded before) and initializing the module invoking the Initialize method.

Based on my understanding, the DirectoryModuleCatalog loads all the assemblies in the specified directory at the beginning. It needs to load them in order to analyze them and build the ModuleInfo for each module. Then, based on those ModuleInfos it initialize the corresponding modules or not accordingly. Hence, it seems the loading of the assembly and the initialization of the module are done at different times.

Regarding loading the modules manually, if you specify that you do not what to load a module automatically at start up then you will need tell Prism when you want this module to be loaded. The simplest way to this is invoking the LoadModule method in the moment you want to initialize the module.

Regards,

Damian Cherubini
http://blogs.southworks.net/dcherubini
Jul 14, 2013 at 11:35 AM
Thanks Damian for your reply.

I don't like DirectoryModuleCatalog way to load all assemblies at the same time as it will bring bad performance. I seek a way to load module manually when it's needed.
Seems that the one way to make this is to use LoadModule as you said.

Here is another issue i encountered when using LoadModule, could you help take a look at it? Senario is below:

I output the assemble of one module in the same folder as the output of the shell app. However, i got error saying "Module ModuleHouseOwnerInfo was not found in this catalog" when using LoadModule with the module name as parameter.

in Bootstrapper.cs class:
    protected override void ConfigureAggregateCatalog()
    {
        base.ConfigureAggregateCatalog();

        this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
    }
The module class:
[ModuleExport(typeof(ModuleHouseOwnerInfo))]
public class ModuleHouseOwnerInfo : IModule
{
    [ImportingConstructor]
    public ModuleHouseOwnerInfo()
    {
    }
}
Developer
Jul 15, 2013 at 7:12 PM
Hi,

It seems that the ModuleHouseOwnerInfo module is not being registered in the ModuleCatalog. The DirectoryModuleCatalog you are using in your application loads the modules from the "DirectoryModules" folder, so as the module is in the shell's folder and not in the aforementioned directory it will not picked up by the DirectoryModuleCatalog (although I'm not seeing it being created in your ConfigureAggregateCatalog method anymore).

In order to load and initialize the module you need to register it, which can be done in several ways:

  • You can move the module to the "DirectoryModules" directory for it to be picked by the DirectoryModuleCatalog (if you are still using it).
  • If you have a direct reference in the Shell to the module, you can add it manually as an AssemblyCatalog, just like you are doing with the Shell in the ConfigureAggregateCatalog method:
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleHouseOwnerInfo).Assembly));
  • You can register the module using a ConfigurationModuleCatalog and add it to the AggregateCatalog too.
You can find more information about to use different methods of registering modules in the following chapter of the documentation:
I hope this helps,

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