Exports are populating the container twice

Topics: Prism v4 - Silverlight 4
Oct 24, 2010 at 10:09 PM

I'm trying to piece together examples and put together a base solution as a template for building modular Silverlight applications.

I'm using MEF.

I'm using a ModulesCatalog.xaml file to load my modules.  Right now there is only 1 module and it's name is module1.

In module1, I found if I didn't override the ConfigureAggregateCatalog, none of my Exports are available in the Module1.xap file.

So I had to override the ConfigureAggregateCatalog as follows:

AggregateCatalog _aggregCat = new AggregateCatalog();

            _aggregCat.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
            _aggregCat.Catalogs.Add(new AssemblyCatalog(typeof(GlobalRegionNames).Assembly));

            foreach (var module in this.ModuleCatalog.Modules)
            {
                _aggregCat.Catalogs.Add(CreateCatalog(module.Ref));
            }

            CompositionHost.Initialize(_aggregCat); //add the current XAP.

 

Here is the code for CreateCatalog I got from the samples:

 

private DeploymentCatalog CreateCatalog(string uri)
        {
            var catalog = new DeploymentCatalog(uri);
            catalog.DownloadCompleted += (s, e) => DownloadCompleted(s, e);
            catalog.DownloadAsync();
            return catalog;
        }

        private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                StringBuilder _sb = new StringBuilder();
                _sb.Append(@"Bootstrapper Module Load Exception: \r\n");
                _sb.Append(e.Error.Message);

                if (e.Error.InnerException != null)
                {                    
                    _sb.Append(e.Error.InnerException);
                }

                MessageBox.Show(e.Error.Message);
            }
        }

In doing this, I now have a problem in the bootstrapper in the CreateShell()

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

I get an exception that the Shell contract is not found though it is exported in the base silverlight project.
 
So I have to go back to the ConfigureAggregateCatalog function and and add this code.
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(GlobalRegionNames).Assembly));
The problem with doing this I have IPopupController and ILogService I export in the base object and they are getting registered 2 times.  So I'm not understanding why the GetExportedValue<Shell> is failing when it is in fact registered.  
 
Oct 25, 2010 at 7:30 PM
Edited Oct 25, 2010 at 7:34 PM

Hi,

I do not know your exact scenario, but take into account that the Quickstarts are meant to provide guidance on an specific topic.

That said, if you are creating a template of a Prism application, I would recommend you to base it on the Stock Trader Reference Implementation. This application ties together most of the design/technical concepts using MEF.

Please take into account that the override of the ConfigureAggregateCatalog method can only be done in classes that inherit from the MEFBootstrapper class. In general, it is located in the Shell project, but not in the modules

If you need more guidance on this topic, you could check how it is implemented in the Stock Trader RI.

Additionally, if you continue experiencing this situation in your scenario, could you please send a repro sample? For example using Windows Live SkyDrive.

Hope this helps.

Fernando Antivero
http://blogs.southworks.net/fantivero

Oct 25, 2010 at 7:35 PM

Thanks Fantivero,

I'm trying to use the Stock trader RI app.  The problem though is it shows how to use ModuleCatalog file to load modules but then it turns around and tightly couples the aggregate container to them by manually adding the modules in the bootstrapper.

I use the code from another example that populates the modules into the aggregateCatalog dynamically based on what's in the ModuleCatalog file.

foreach (var module in this.ModuleCatalog.Modules)
            {
                _aggregCat.Catalogs.Add(CreateCatalog(module.Ref));
            }

All of this is done in the bootstrapper and yes it inherits from MEFBootstrapper.  When I get home this afternoon I'll figure out a way to post the solution.

 

 

 

 

Oct 25, 2010 at 7:48 PM

Here's a link

http://cid-ff05a29e13af7bfd.office.live.com/self.aspx/.Public/Code%20Samples#resId/FF05A29E13AF7BFD!229

If you need to compile this, you can pull down the Telerik trial assemblies

http://www.telerik.com/login.aspx?ReturnUrl=%2faccount%2ffree-trials%2ftrial-product-versions%2fsingle-trial.aspx%3fpmvid%3d0%26pid%3d571

Start by looking in the ConfigureAggregateCatalog function. 

this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(GlobalRegionNames).Assembly));

            // This was the only way that the Module1 was satisfying it's import is with the code below.
            // In EyeCue that's how it was at least.
            AggregateCatalog _aggregCat = new AggregateCatalog();

            _aggregCat.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
            _aggregCat.Catalogs.Add(new AssemblyCatalog(typeof(GlobalRegionNames).Assembly));

You see I'm having to populate two containers here.  If I don't do the first one, then the Shell isn't available in the CreateShell override.

If I don't add the second AggregateCatalog then when I start adding multiple Modules in different .Xaps, I find that IPopupController isn't available.  In this small template, I don't have the problem with IPopupcontroller not being in Module1.  However, at work, I have a separate solution with multiple modules, and this is what I had to do to get things to work.

Note, I don't want to have to add references in my base silverlight project to modules like what is happening in the StockTrader RI sample.