Export / Import in Bootstrapper

Topics: Prism v4 - WPF 4
Jun 27, 2010 at 6:41 AM

I'm unable to Export / Import within the Bootstrapper - is there a "Container.Buildup" equivalent in MEF?  

In my MVPVM refactor of the ModularityWithMef sample, everything went smoothly until I tried to export the MainWindow's presenter (so I could move the Imports out from code-behind into the Presenter).  

MVPVM ModularityWithMef sample available on the following link:

http://www.global-webnet.net/blogengine/post/2010/06/26/PRISM-V4-Drop-2-MVPVM-Modularity-with-MEF.aspx

 

Jun 27, 2010 at 6:05 PM

Bill,

Your link is broken...

 

Morgan.

Jun 27, 2010 at 6:10 PM
mvermef wrote:

Bill,

Your link is broken...

 Morgan.

 Thanks Morgan, I failed to publish the blog entry - it is available now.

Jun 30, 2010 at 11:56 PM

Hi Bill,


There's a few ways you can access parts via the container from within your Boostrapper class.  The difficulty is that the boostrapper creates the container itself, so probably shouldn't have declarative attributes on itself.  As well, the boostrapper isn't meant to have a long lifetime either, so the recommendation is to do imports/exports using other classes.


Option A: Compose an instance directly

1. Create a class that uses [Import] (and/or [Export])

2. Override ConfigureContainer and instantiate your type, then call this.Container.ComposeExportedValue. 

The MefBootstrapper does this for all the types that it or derived classes instantiate directly before the container is available.

    Example: Composing the logger.

    this.Container.ComposeExportedValue<ILoggerFacade>(this.Logger);

Option B: Satisfy imports to compse the Boostrapper.

I think of the MEF container kind of like the .NET garbage collector.  The GC works from a root object and walks down a tree of everything that is referenced - anything not in the tree is a candidate for collection.  The MEF container might know about a bunch of exported types via its catalog, but doesn't really start resolving something until composes something that needs to resolve [Import] statements. The container then uses exports to resolve imports which might cause the need to resolve more imports.

The MEF container doesn't know about the Boostrapper by default and no one asks to compose it, so imports are not resolved.  Plus, you've already instantiated the Bootstrapper, so you'll have to put imports on fields/properties that allow recomposition.

1. Add a field or get/set property to your Boostrapper and place an [Import(AllowRecomposition=true)] attribute on it.  

2. Override ConfigureContainer and call this.Container.ComposeParts(this).

2b. Alternatively, you could call this.Container.SatisfyImportsOnce(this) if you only want to satisfy the imports a single time.

Before using your type, you may want to wait until the imports are satisfied.  The Shell.xaml.cs uses this technique.

3. Add IPartImportsSatisfiedNotification interface to the Boostrapper declaration.

4. Implement OnImportsSatisfied() and use your new type there.

I'm not sure if Option B is a good idea because then the container is holding a reference to something holding a reference to the container.  This could cause a memory leak (at least until the app domain terminates).

If you have troubles, could you put some commented out code in your sample application of what you would like to have and I can try and work through how the container could resolve it for you.

Hope this helps,

Geoff Cox
Southworks

Jul 1, 2010 at 12:11 PM

Yes Geoff, this helps alot; you gave me a number of options to work with (and more importantly a better understanding).  I'll probably try both options as I refactor the Bootstrapper to create child containers for each module; something I do with Unity.   I want to upgrade the sample so that when you click on the green module box that it will unload the module (as in Disposing the container and all child objects to reclaim memory) and permit me to reload it.