Prism Talk at Sweden .NET Users Group – MEF Modularity Differences

Last night I gave a talk on Prism at the Sweden .NET User Group. It was a great crowd with lots of great questions. Thanks to Tibi and Ulf for inviting me to speak.

I had one little glitch on an on-the-fly demo that I thought I would just put out there as a tip and trick since it tripped me up and I am supposed to be an expert on Prism.

In Prism 4 the option was added to use MEF for the dependency injection container that you can use instead of Unity, since MEF is now part of the framework. That means you have to use MEF attributes to indicate your Exports (similar to registering types with the container in Unity) and Imports (similar to Resolving types with Unity). In my demo, I quickly put together a shell application and a single module with a single view and was placing the view into a region in the shell.

The code for the bootstrapper looks like this:

1:class Bootstrapper : MefBootstrapper

2: {

3:protectedoverride System.Windows.DependencyObject CreateShell()

4: {

5: MainWindow win = new MainWindow();

6: win.Show();

7:return win;

8: }

9:

10:protectedoverride IModuleCatalog CreateModuleCatalog()

11: {

12:returnnew ModuleCatalog().AddModule(typeof(Module1.Module));

13: }

14:

15:protectedoverridevoid ConfigureAggregateCatalog()

16: {

17:base.ConfigureAggregateCatalog();

18: AggregateCatalog.Catalogs.Add(

19:new AssemblyCatalog(typeof(Module1.Module).Assembly));

20: }

21: }



One thing thing that is different about using MEF in Prism 4 from the way this was done with Unity is the need to add your module assemblies to the AggregateCatalog that is used in the bootstrapper, seen in the ConfigureAggregateCatalog method at the bottom. This makes it so MEF will probe those assemblies and discover the Exports within them. The bootstrapper will automatically discover types in the shell, but you need to tell it what other assemblies you want to have added to the catalog.

Then the module class looks like this:

1: [ModuleExport(typeof(Module))]

2:publicclass Module : IModule

3: {

4: IRegionManager _RegionManager;

5: [ImportingConstructor]

6:public Module(IRegionManager regionManager)

7: {

8: _RegionManager = regionManager;

9: }

10:publicvoid Initialize()

11: {

12: _RegionManager.RegisterViewWithRegion("MainContent",typeof(UserControl1));

13: }

14: }

Notice that the module needs to Export itself using a custom Export attribute that is part of Prism (think of it as combining the declaration of Export in MEF with the declaration that this is a Module to Prism. I use an [ImportingConstructor] attribute from MEF to indicate the dependencies I need injected, which in this case is just the region manager. The “MainContent” region is declared in the shell with a normal RegionName attached property.

The thing that tripped me up in my demo is that I forgot to put an Export on the UserControl1 that I was using as a view with the RegisterViewWithRegion view discovery mechanism of Prism. I needed to do this:

1: [Export]

2:publicpartialclass UserControl1 : UserControl

3: {...}



The reason is that RegisterViewWithRegion uses the container to construct the specified view type. With MEF, the container can’t construct a type unless that type has been marked as an Export in the catalog managed by the container. If I had passed a reference to the view into RegisterViewWithRegion, it would not have been a problem because I could have just new’d up the view myself. But if you use the overload of RegisterViewWithRegion that takes a view type name, Prism uses the container to construct the type, which requires proper registration with the container. For Unity, this would have been no problem because Unity can construct any concrete type without registration by reflecting on its constructors. But MEF always requires the type to be exported in the catalog. Unity 1, MEF 0 in my mind, but maybe I just need to get more used to the Meffy way of doing things. :)

Here are the Slides and Demos from the talk.