StaticModuleEnumerator stopping dynamic loading of modules?

Oct 28, 2008 at 5:28 AM
Hi all,

I'm trying to load a module on demand (ie not during app start-up).

I've read a few posts here, and this article;

http://msdn.microsoft.com/en-us/library/cc707860.aspx

but... I can't get it to work.

I've;

1) used a StaticModuleEnumerator in my bootstrapper (me thinks this is the cause of my problems!)
2) added the StartupLoaded attribute to my module

but the module is still loaded when the app starts up.

When I run the DirectoryLookupModularity quickstart, its ModuleC does NOT load on app start-up. I can't see any difference between my app and that quickstart other than it uses the DirectoryLookupModuleEnumerator.


Any tips? Thanks in advance!

here's some of my code;


 

class Bootstrapper : UnityBootstrapper

 

{

 

protected override DependencyObject CreateShell()

 

{

 

Shell shell = Container.Resolve<Shell>();

 

shell.Show();

 

return shell;

 

}

 

protected override IModuleEnumerator GetModuleEnumerator()

 

{

 

return new StaticModuleEnumerator()

 

.AddModule(

typeof(TestModule01.TestModule01Module));

 

}

}



namespace

 

TestModule01

 

{

[

Module(ModuleName = "TestModule01Module", StartupLoaded = false)]

 

 

public class TestModule01Module : IModule

 

{

 

private readonly IRegionManager _regionManager;

 

 

public TestModule01Module(IRegionManager regionManager)

 

{

_regionManager = regionManager;

}

 

public void Initialize()

 

{

_regionManager.Regions[

"MainRegion"].Add(new Views.UC02());

 

}

}

}



Oct 28, 2008 at 1:08 PM
Edited Oct 28, 2008 at 1:14 PM

Hi,

 

As you have stated, the reason why your module is loaded at startup is the StaticModuleEnumerator class. When adding a module, it uses a constructor of the ModuleInfo class that sets the StartUpLoaded to true by default and sends the name of the type of the module as its module name, so it does not allow you to establish when your module gets loaded nor a custom name for it.

 

Regarding the Module attribute, it is only used by the DirectoryLookupModuleEnumerator class, that’s why the module is not loaded at startup when you use this module enumerator.

 

If you want to set both, name and StartUpLoaded properties of the module, I recommend you to use the DirectoryLookupModuleEnumerator with the Module attribute or the ConfigurationModuleEnumerator with a configuration file.

 

Perhaps you may find useful the following articles that explains the Module concept and the different types of Module Loading.

·         Module

·         How to: Dynamically Load Modules

 

Please, let me know if this helps.

 

Ignacio Baumann Fonay

http://blogs.southworks.net/ibaumann/

Oct 28, 2008 at 2:17 PM
Thanks Ignacio, your post did help. To clarify, that is.

I must admit, though, that I find the whole thing a little strange.

The StaticModuleEnumerator has so many benefits, all listed in the documentation, but it 'now' (from my POV) has a pretty serious flaw - every single module in my app has to be initialized when the app starts... and I lose the ability to dynamically load modules.

I'm sure this will change in the future - it's just a pity this release didn't have it.

thanks again
Oct 28, 2008 at 4:30 PM

Hi,

 

If you need to statically load some modules at startup and some others dynamically on demand, what you could do is override the InitializeModules() method of the Bootstrapper. Then, you should call the base.InitializeModules() method, so that it uses the module enumerator (in your case, a ConfigurationModuleEnumerator, for example, to load the other modules on demand) and the module loader classes. I.e.:

public class Bootstrapper : UnityBootstrapper

{

    protected override DependencyObject CreateShell()  {    //…        }

 

    protected override void InitializeModules()

    {

        IModule myModule = Container.Resolve<MyModule>();

        IModule myOtherModule = Container.Resolve<MyOtherModule>();

 

        myModule.Initialize();

        myOtherModule.Initialize();

 

        base.InitializeModules();

    }

 

    protected override IModuleEnumerator GetModuleEnumerator()

    {

        return new ConfigurationModuleEnumerator();

    }

}

 

Another possible approach would be to combine the module enumerators as shown in Willem Meint’s blog post Combining module enumerators in CompositeWPF.

 

Hope it helps.

 

Ignacio Baumann Fonay

http://blogs.southworks.net/ibaumann/

Oct 29, 2008 at 12:46 AM
Hi gfdarcy,

The reasoning behind it is that if you have a static reference to the type (to be able to do typeof when adding the module), then it means that your assemblies for that module are already loaded in the AppDomain.
You could potentially still want to delay the instantation of the class that implements IModule, but another way to see it, is that the class that implements IModule is extremelly lightweight, and all the Initialize() method does is register some types in the container (optional), and adds a command somewhere in order to be called "on demand" (or this could be a subscription to an event in the EventAggregator), and until then the module is loaded but standing by (therefore very lightwight until needed).
The reasoning behind the "startup loaded" piece, is that for those modules that are on demand, their assemblies may not be even loaded in the AppDomain until trying to initialize them, which is where you may see some gain in the application footprint or load time, where you could for example have lots and lots of modules sitting in a directory.

I hope this helps clarifying the reasoning behind the decision of not having that option in the StaticModuleEnumerator class. Of course feedback is always welcomed.

Julian Dominguez
http://blogs.southworks.net/jdominguez
Oct 29, 2008 at 8:30 AM
Thank you both, your answers have helped plenty.

I think I panicked a little thinking that 'initialize all modules' was the same as 'initialize all VIEWS'. That's obviously not the case.