How To: Load modules on demand that have dependencies using Composite WPF (Prism)
The Composite Application Guidance for WPF - June 2008 release brings out-of-the-box support to load modules on demand. The only thing that you need to do is set the StartupLoaded property of the module to false. This feature is provided by the following Module Enumerators classes:
- The DirectoryLookupModuleEnumerator class that discovers modules in assemblies stored in a particular folder. This approach requires you to configure modules using attributes in code like the following:
[Module(ModuleName = "ModuleB", StartupLoaded = false)] public class ModuleB : IModule { //… }
For more information see: Using the Directory Lookup Module Enumerator.
- The ConfigurationModuleEnumerator class that discovers modules by reading the configuration file of the application. This approach requires a configuration file. The following code shows the content of a sample App.config file:
<?xml version=“1.0” encoding=“utf-8” ?> <configuration> <configSections> <section name=“modules” type=“Microsoft.Practices.Composite.Modularity.ModulesConfigurationSection, Microsoft.Practices.Composite“/> </configSections> <modules> <module assemblyFile=“Modules/ModuleA.dll” moduleType=“ModuleA.ModuleA” moduleName=“ModuleA“/> <module assemblyFile=“Modules/ModuleB.dll” moduleType=“ModuleB.ModuleB” moduleName=“ModuleB” startupLoaded=“false“ /> </modules> </configuration>
For more information see: Using the Configuration Module Enumerator.
Specifying Modules Dependencies
The mentioned Module Enumerators allow you to specify dependencies on the modules. In this way the Module Loader initializes first all its dependent modules before loading it.
- With the DirectoryLookupModuleEnumerator class the dependencies are specified with the ModuleDependecy attribute.
[Module(ModuleName = "ModuleB", StartupLoaded = false)] [ModuleDependency("ModuleA")] public class ModuleB : IModule { //… }
- With the ConfigurationModuleEnumerator class the dependencies are specified with the depedencies node in the configuration file:
<?xml version=“1.0” encoding=“utf-8” ?> <configuration> <configSections> <section name=“modules” type=“Microsoft.Practices.Composite.Modularity.ModulesConfigurationSection, Microsoft.Practices.Composite“/> </configSections> <modules> <module assemblyFile=“Modules/ModuleA.dll” moduleType=“ModuleA.ModuleA” moduleName=“ModuleA“/> <module assemblyFile=“Modules/ModuleB.dll” moduleType=“ModuleB.ModuleB” moduleName=“ModuleB” startupLoaded=“false” /> <dependencies> <dependency moduleName=“ModuleA“/> </dependencies> </modules> </modules> </configuration>
The current release of the Composite Application Library do not bring support for loading modules on demand with dependencies. If you try to do this, you will get a ModuleLoadException exception with the message: A module declared a dependency on another module which is not declared to be loaded. Missing module(s).

Cause of the ModuleLoadException
To load a module the Composite Application Library provides the a Module Loader class. This class contains the Initialize method that receives the list of the modules that you want to load as a parameter.
public LoadModuleB(IModuleLoader moduleLoader, IModuleEnumerator moduleEnumerator) { ModuleInfo[] modules = new ModuleInfo[] { moduleEnumerator.GetModule(“ModuleB”) }; moduleLoader.Initialize(modules); }
The Module Loader assumes that the list of modules passed to its Initialize method also includes the dependencies. That is why it throws the exception: A module declared a dependency on another module which is not declared to be loaded when you want to load a single module on demand with dependencies (the module’s dependencies are not present in the list).
Workaround
A workaround to solve this issue could be creating an extension method to the Module Enumerator class that returns the module and its dependencies. The following is a possible implementation:
using System.Linq; using System.Collections.Generic; // The namespace is important to make the extension method work. namespace Microsoft.Practices.Composite.Modularity { public static class ModuleEnumeratorExtensions { public static ModuleInfo[] GetModuleWithDependencies(this IModuleEnumerator moduleEnumerator, string moduleName) { List<ModuleInfo> moduleInfoList = new List<ModuleInfo>(); ModuleInfo module = moduleEnumerator.GetModule(moduleName); moduleInfoList.Add(module); if (module.DependsOn != null) { foreach (string dependencyName in module.DependsOn) { if (!moduleInfoList.Exists(existingModule => existingModule.ModuleName == dependencyName)) { moduleInfoList.AddRange(GetModuleWithDependencies(moduleEnumerator, dependencyName)); } } } return moduleInfoList.ToArray(); } } }
Then, when you need to initialize a module on demand you can use the previous extension method in the following way:
public DefaultViewB(IModuleLoader moduleLoader, IModuleEnumerator moduleEnumerator) { moduleLoader.Initialize( moduleEnumerator.GetModuleWithDependencies(“ModuleB”) ); }
Enjoy
