Unity + MEF Integration with UnityBootStrapper

Jan 7, 2011 at 2:29 AM

I am trying to convert the Prism v4 ModularityWithUnity.Desktop sample over to use Unity + Mef integration.
I changed ModuleA and ModuleD over to use attributes also making sure to change the output directory for ModuleD and commenting out ModuleA in the ConfigureModuleCatalog().
I then added the CreateContainer override.

The unity modules are loading fine but my ModuleA and ModuleD constructors are not being called.

Is there anything else I need to do get this working?

using System;
using System.ComponentModel.Composition.Hosting;
using System.Windows;
using MefContrib.Integration.Unity;
using Microsoft.Practices.Prism.Logging;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Prism.UnityExtensions;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
using ModuleTracking;

public class QuickStartBootstrapper : UnityBootstrapper
{
    private readonly CallbackLogger callbackLogger = new CallbackLogger();

    protected override IUnityContainer CreateContainer()
    {
        var unityContainer = new UnityContainer();
        var aggregateCatalog = new AggregateCatalog();

        aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleA).Assembly));

        DirectoryCatalog catalog = new DirectoryCatalog("DirectoryMefModules");
        aggregateCatalog.Catalogs.Add(catalog);

        unityContainer.RegisterCatalog(aggregateCatalog);

        return unityContainer;
    }

    protected override DependencyObject CreateShell()
    {
        return ServiceLocator.Current.GetInstance<Shell>();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();

        Application.Current.MainWindow = (Window)this.Shell;
        Application.Current.MainWindow.Show();
    }

    protected override ILoggerFacade CreateLogger()
    {
        // Because the Shell is displayed after most of the interesting boostrapper work has been performed,
        // this quickstart uses a special logger class to hold on to early log entries and display them 
        // after the UI is visible.
        return this.callbackLogger;
    }

    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();

        this.RegisterTypeIfMissing(typeof(IModuleTracker), typeof(ModuleTracker), true);

        this.Container.RegisterInstance<CallbackLogger>(this.callbackLogger);
    }

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

    protected override void ConfigureModuleCatalog()
    {
        // Module A is defined in the code.
        //Type moduleAType = typeof(ModuleA);
        //ModuleCatalog.AddModule(new ModuleInfo(moduleAType.Name, moduleAType.AssemblyQualifiedName));

        // Module C is defined in the code.
        Type moduleCType = typeof(ModuleC);
        ModuleCatalog.AddModule(new ModuleInfo()
        {
            ModuleName = moduleCType.Name,
            ModuleType = moduleCType.AssemblyQualifiedName,
            InitializationMode = InitializationMode.OnDemand
        });

        // Module B and Module D are copied to a directory as part of a post-build step.
        // These modules are not referenced in the project and are discovered by inspecting a directory.
        // Both projects have a post-build step to copy themselves into that directory.
        DirectoryModuleCatalog directoryCatalog = new DirectoryModuleCatalog() { ModulePath = @".\DirectoryModules" };
        ((AggregateModuleCatalog)ModuleCatalog).AddCatalog(directoryCatalog);

        // Module E and Module F are defined in configuration.
        ConfigurationModuleCatalog configurationCatalog = new ConfigurationModuleCatalog();
        ((AggregateModuleCatalog)ModuleCatalog).AddCatalog(configurationCatalog);

    }
}

// ----
[ModuleExport(typeof(ModuleD))]
public class ModuleD : IModule
{
        [ImportingConstructor]
        public ModuleD(IModuleTracker moduleTracker)

[ModuleExport(typeof(ModuleA), DependsOnModuleNames = new string[] { "ModuleD" })]
public class ModuleA : IModule
{
        [ImportingConstructor]
        public ModuleA(ILoggerFacade logger, IModuleTracker moduleTracker)


Jun 30, 2011 at 3:01 PM

hi, xiquon : did you find anything on the subject ?

 

I'm running in the same problem and was wondering if you'd managed to get those Modules to be properly initialized.

 

-Fabio

Aug 27, 2011 at 8:59 AM
Edited Aug 27, 2011 at 8:59 AM

1. You should add Microsoft.Practices.Prism.MefExtensions

2. Register MEF catalog in unity:

protected override IUnityContainer CreateContainer()

{

...

unityContainer.RegisterInstance(aggregateCatalog);

}

3. Use MefModuleManager from Prism.MefExtensions as IModuleManager. Add next lines to the end of ConfigureContainer:

protected override void ConfigureContainer()
        {
            ...
 
            var catalog = new TypeCatalog(typeof(MefFileModuleTypeLoader));
            Container.Resolve<AggregateCatalog>().Catalogs.Add(catalog);
            Container.RegisterType<IModuleManagerMefModuleManager>();
        }

Enjoy!