Module initialization problem

Topics: Prism v4 - WPF 4
Feb 13, 2014 at 12:08 PM
Hi,

I develop a MEF application with Prism 4.5.1 and I have a problem with the initialization of modules. I use a DirectoryCatalog to load my modules. All works fine, but if I import IModuleManager to my ShellViewModel constructor, all modules were loaded before my bootstrapper call the InitializeModules method. So it isn't possible for me to subscribe a event in the shell before the modules raise the event.

Workflow without module manager:
  1. Bootstrapper.CreateShell
  2. Load ShellViewModel
  3. Subscribe event in ShellViewModel constructor
  4. Bootstrapper.InitializeModules
  5. Load modules.
  6. Raise event in Initialize method of module.
Workflow with module manager:
  1. Bootstrapper.CreateShell
  2. Load modules.
  3. Raise event in Initialize method of module.
  4. Load ShellViewModel
  5. Subscribe event in ShellViewModel constructor
  6. Bootstrapper.InitializeModules
Sample module code
[ModuleExport(typeof(SampleModuleA))]
public class SampleModuleA : IModule
{
    [ImportingConstructor]
    public SampleModuleA(IEventAggregator eventAggregator)
    {
        _eventAggregator = eventAggregator;
    }

    public void Initialize()
    {
        _eventAggregator.GetEvent<NewComponentAvailableEvent>().Publish("ComponentA");
    }

    private readonly IEventAggregator _eventAggregator;
}
Sample shell view model code
[Export]
public class ShellViewModel
{
    [ImportingConstructor]
    public MainViewModel(IEventAggregator eventAggregator, IModuleManager manager) // with ModuleManager
    {
        _eventAggregator = eventAggregator;

        _eventAggregator.GetEvent<NewModuleAvailableEvent>().Subscribe(args => {}, ThreadOption.UIThread);
    }

    private readonly IEventAggregator _eventAggregator;
}
Sample bootstrapper code
public class Bootstrapper : MefBootstrapper
{
    protected override void ConfigureAggregateCatalog()
    {
        base.ConfigureAggregateCatalog();

        this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
        this.AggregateCatalog.Catalogs.Add(new DirectoryCatalog("Modules"));
    }

    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new ConfigurationModuleCatalog();
    }

    protected override void InitializeModules()
    {
        base.InitializeModules();
    }

    protected override DependencyObject CreateShell()
    {
        return this.Container.GetExportedValue<Shell>();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();
        Application.Current.MainWindow = (Window)this.Shell;
        Application.Current.MainWindow.Show();
    }
}
Feb 13, 2014 at 5:22 PM
Edited Feb 13, 2014 at 5:22 PM
Hi,

Based on my understanding you would like a possible workaround in order to import the IModuleManager into the ShellViewModel and properly handle every published event from modules initialization.

One simple way you could achieve this is to remove the publish statements from the initialize() methods, and wait instead until the BootStrapper initialization process finishes. Therefore, you could override the Run() method and publish a BootStrapperInitializationCompletedEvent event when it finishes running base method.

Basically, you would need to perform the following updates from the Modules side:

  • Remove publish statement from each Module initialize() method;
  • Add a suscription on each Module initialize() method for the BootStrapperInitializationCompletedEvent event;
  • Handle the BootStrapperInitializationCompletedEvent event and publish the corresponding Module event that was previously removed from the initialize() method.
And then, from the BootStrapper side you should perform the following:

  • Override Run() method by implementing the base.Run(); statement and publishing the BootStrapperInitializationCompletedEvent event.
The ShellViewModel would remain as you described, with no changes. This way, the BootStrapper would publish an event after everything got initialized, giving the green light to every Module to publish their events, knowing that the ShellViewModel is already suscribed to them.

I hope this helped,
Regards.

Gabriel Ostrowsky
https://blogs.southworks.net/gostrowsky
Feb 14, 2014 at 6:58 AM
This helps me a lot! It works well!

Thank you!