images Workshop: Configuring Catalogs and Downloading Modules

So far, we've been using the default composition container and the default catalog that it uses. In this workshop, we're going to take control of the catalogs being used by the default composition container. We'll configure two DeploymentCatalog catalogs to use parts from—one to find parts in the current XAP file, and another that will download another XAP file and find parts in it. We'll then tie these together using an AggregateCatalog catalog, and associate them with the default container.

  1. This workshop will extend the previous workshop to allow the discovery of parts that export themselves using the IPersonPart interface as their contract across multiple XAP files. The first step is to create a new “common” assembly that will contain the interface, which both XAP files can reference. Add a new project to the solution named Chapter14Sample.Common, using the Silverlight Class Library project template.
  2. Move the IPersonPart interface from the Chapter14Sample project to this new Chapter14Sample.Common project.
  3. The Chapter14Sample project needs a reference to the Chapter14Sample.Common project. Add this now. If you compile and run your project, it should run as per the previous workshop.
  4. Let's now configure the catalogs that the default composition container should use. Start by adding the following using statement to the top of the MainPage.xaml.cs file:
    using System.ComponentModel.Composition.Hosting;
  5. Add the following code in bold to the MainPage class's constructor:
    public MainPage()
    {
        InitializeComponent();

        var aggregateCatalog = new AggregateCatalog();

        var catalog1 = new DeploymentCatalog();
        aggregateCatalog.Catalogs.Add(catalog1);

        CompositionHost.Initialize(aggregateCatalog);
        CompositionInitializer.SatisfyImports(this);

        var list = new ListBox();
        list.ItemsSource = MyImportedPersonParts;
        list.DisplayMemberPath = "Name";
        LayoutRoot.Children.Add(list);
    }

    In this code, we've added a DeploymentCatalog instance to an AggregateCatalog catalog, and passed the AggregateCatalog catalog to the CompositionHost to use. The DeploymentCatalog catalog is configured to simply look in the current XAP file for any exports. Once again, if you compile and run your project, it should run as per the previous workshop.

  6. Now we'll create a new “module” that will be compiled into its own XAP file, and downloaded by another DeploymentCatalog catalog. Add a new project to the solution named Module1, using the Silverlight Application project template. Deselect the “Add a test page that references the application” check box in the wizard that appears, and click OK.
  7. Add the following references to the project:
    • System.ComponentModel.Composition.dll
    • Chapter14Sample.Common.dll (as a project reference)
  8. Add a new class to the module project, named YetAnotherPersonPart.cs.
  9. This class will be just like the PersonPart and AnotherPersonPart classes that you created in the previous workshops. Simply assign another name to the Name property in its constructor to differentiate it from the other classes.
    using System.ComponentModel.Composition;

    namespace Module1
    {
        [Export(typeof(IPersonPart))]
        public class YetAnotherPersonPart : IPersonPart
        {
            public string Name { get; set; }

            public YetAnotherPersonPart()
            {
                Name = "Bart Simpson";
            }
        }
    }
  10. Open the MainPage class in the Chapter14Sample project. We now need to create a new DeploymentCatalog instance that points to the XAP file of the module that we just created, and add it to the AggregateCatalog catalog. Add the following code in bold to the MainPage class's constructor:
    public MainPage()
    {
        InitializeComponent();

        var aggregateCatalog = new AggregateCatalog();

        var catalog1 = new DeploymentCatalog();
        aggregateCatalog.Catalogs.Add(catalog1);

        var catalog2 =
            new DeploymentCatalog(new Uri("Module1.xap", UriKind.Relative));
        catalog2.DownloadAsync();
        aggregateCatalog.Catalogs.Add(catalog2);

        CompositionHost.Initialize(aggregateCatalog);
        CompositionInitializer.SatisfyImports(this);

        var list = new ListBox();
        list.ItemsSource = MyImportedPersonParts;
        list.DisplayMemberPath = "Name";
        LayoutRoot.Children.Add(list);
    }
  11. The final step is to allow the MyImportedPersonParts property to support recomposition. This will allow it to be updated with new parts as they become available (i.e., after the module XAP file has been downloaded).
    [ImportMany(AllowRecomposition=true)]
    public ObservableCollection<IPersonPart> MyImportedPersonParts { get; set; }

    Note how the type was changed from an array to an observable collection. MEF will update this collection as parts become available, and being an observable collection means that the ListBox control will be aware of the changes and update itself accordingly. This will require the following using statement to be added to the top of the file:

    using System.Collections.ObjectModel;

    The final code that you should have for the MainPage class is as follows:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Windows.Controls;

    namespace Chapter14Sample
    {
        public partial class MainPage : UserControl
        {
            [ImportMany(AllowRecomposition=true)]
            public ObservableCollection<IPersonPart> MyImportedPersonParts
                { get; set; }

            public MainPage()
            {
                InitializeComponent();

                var aggregateCatalog = new AggregateCatalog();

                var catalog1 = new DeploymentCatalog();
                aggregateCatalog.Catalogs.Add(catalog1);

                var catalog2 =
                   new DeploymentCatalog(new Uri("Module1.xap", UriKind.Relative));
                catalog2.DownloadAsync();
                aggregateCatalog.Catalogs.Add(catalog2);

                CompositionHost.Initialize(aggregateCatalog);
                CompositionInitializer.SatisfyImports(this);

                var list = new ListBox();
                list.ItemsSource = MyImportedPersonParts;
                list.DisplayMemberPath = "Name";
                LayoutRoot.Children.Add(list);
            }
        }
    }
  12. Now run your application. You should see three names appear in the list: Homer Simpson and Marge Simpson (from the main application's XAP file), and Bart Simpson (from the module).

images Note The Chapter14Sample.Common.dll assembly will be compiled into both the Chapter14Sample.xap and Module1.xap files. You can use Silverlight's assembly caching feature, covered in Chapter 17, to download the assembly independently from both XAP files, resulting in only one copy needing to be downloaded to the client. This is rather important when you have many shared libraries between the “shell application” and the modules, especially when the shared libraries are sizable.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.119.114