We deliver solutions that
accelerate the value of Azure.

PRISM, MEF, and MVVM Part 3 of 3: Dynamic MEF Modules in PRISM

Contact Us Today

Series recap:

In the final part of this series, I will show a dynamically loaded module (using PRISM) that takes full advantage of MEF.

Here is a preview of the final product, illustrating the different modules and areas I have pulled together to demonstrate (click for a full resolution view):

Download the Source for this Example

Why even bother with dynamic modules? Dynamic module loading can be a powerful way to build scalable (and more stable) applications in Silverlight. By creating dynamic modules, you ensure the user only loads what they need, when they need it. The dynamic module only comes into play when the user demands a feature that requires the module.

Before we dive into the new MEF-based module, let’s break down a few best practices when using dynamically loaded modules:

  • The best option I’ve found for this so far is to use PRISM’s “on demand” functionality for loading modules.
  • Typically, you will want to put your main dependencies in the “main” or “host” Silverlight project.
  • Create a new dynamic module by adding a Silverlight Application project, not a Silverlight Class Library.
  • Use a XAML catalog to reference the dynamic modules. This gives PRISM something to resolve when the new module is requested, but avoids direct dependencies on the satellite modules by the main application.
  • When referencing projects or DLLs that are part of the main application in a satellite module, be sure to set “copy local” to false. This ensures these are not compiled into the XAP, because the module can leverage the fact that the main module has already loaded the dependencies. This leads to very lightweight XAP files.

When everything comes together as planned, you can scan traffic with a tool like Fiddler to see what happens. Take a look at this example. Here, you can clearly see the satellite modules are loaded dynamically. In fact, the MEF module, which displays a list and dynamically displays a child view, weighs in at only 5,000 bytes!

Click here to view the Fiddler snapshot

I started by adding a new Silverlight Application and calling it MEFModule.

The MEF ViewModel

The MEF view model looks like this:

[Export]
public class MoreStuffViewModel : IPartImportsSatisfiedNotification
{        
    private IService _service; 

    [Import]
    public IService Service
    {
        get { return _service; }
        set
        {
            _service = value;
            if (_service != null)
            {
                _service.GetMoreStuff(_ServiceLoaded); 
            }
        }
    }

    [ImportMany("MoreStuff",AllowRecomposition=true)]
    public List<string> ImportedStuff { get; set; }

    [Import]
    public IRegionManager RegionManager { get; set; }

    public DelegateCommand<object> DynamicViewCommand { get; set; }

    [Import("DynamicView")] 
    public object DynamicView { get; set; }

    private ObservableCollection<string> _listOfMoreStuff;

    public MoreStuffViewModel()
    {
        // initialize all lists
        _listOfMoreStuff = new ObservableCollection<string>();
        DynamicViewCommand = new DelegateCommand<object>(o =>
            {
                RegionManager.RegisterViewWithRegion("MainRegion", () => DynamicView);
            });
    }

    private void _ServiceLoaded(List<string> values)
    {
        foreach (string value in values)
        {
            _listOfMoreStuff.Add(value);
        }
    }
       
    public ObservableCollection<string> ListOfMoreStuff 
    {
        get
        {
            return _listOfMoreStuff;
        }

        set
        {
            _listOfMoreStuff = value; 
        }
    }

    #region IPartImportsSatisfiedNotification Members

    public void OnImportsSatisfied()
    {
        foreach (string importedValue in ImportedStuff)
        {
            _listOfMoreStuff.Add(importedValue);
        }
    }

    #endregion
}

I’ve purposefully loaded this view model with tons of goodies to help understand and take advantage of MEF to its fullest. You’ll notice two things right away about the view model: it is exported using the Export attribute, and it implements an interface called IPartImportsSatisfiedNotification. When you implement this interface, MEF will automatically call OnImportsSatisfied, allowing you to react to the new imports.

You’ll notice I have a collection called ImportedStuff that imports a contract with a magic string (tip: in a production project this would probably be a type or an enumeration or at least a static class with a constant to allow for type checking) called MoreStuff. We’ll give this collection what it needs somewhere else, for now it is simply waiting for imports and when those imports are satisfied, we merge them into our master ListOfMoreStuff collection.

We also reference IService. If you remember, when we set that up back in part 1, we went ahead and added an Export tag. Here, we import it. Notice that on the setter, when the import happens, I go ahead and call the GetMoreStuff method, which returns me the Spanish numbers. When these are loaded, we merge them into our master ListOfMoreStuff. So the list will contain the results of the service call and any MoreStuff imports we may find.

We also want to dynamically display another view, but we don’t know what that view is yet. Remember in part 2 I explicitly set the export value of IRegionManager using Unity to resolve it? This is where we will import it!

The DynamicViewCommand gives us a command to bind to in order to show that view. The view gets imported with another magic string (again, just stating I know we don’t like them, but they are there for the sake of brevity in this example only) called DynamicView. In the constructor for the view model, we bind the command to a call to RegisterViewWithRegion and pass in the dynamic view.

This demonstrates how powerful MEF really is: we are able to specify an action to dynamically show a view here in the view model without any prior knowledge of where the view is or even what it is composed of!

The rest of the view model code simply initializes lists, combines them, etc. We’ve got our view model in place. How about some views that use it?

The MEF Views

In the views folder, I created two views. The first or “main” view is simply called MoreStuffView and it binds to the ListOfMoreStuff collection as well as the dynamic view command:

<ListBox ItemsSource="{Binding ListOfMoreStuff}">
   <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<Button Grid.Column="1" cal:Click.Command="{Binding DynamicViewCommand}" Content="Add View"/>

The code behind requires two pieces: first, we need to import the view model and bind it:

[Import]
public MoreStuffViewModel ViewModel
{
   get { return (MoreStuffViewModel)LayoutRoot.DataContext; }
   set { LayoutRoot.DataContext = value; }
}

Next, we need to call our friend, the PartInitializer class, to satisfy all of the imports in the constructor:

public MoreStuffView()
{            
    InitializeComponent();           
    PartInitializer.SatisfyImports(this);                
}

And that’s it … all of the services, exports, etc will be wired in elsewhere. I created a second view called DynamicView. This view simply contains a text block that indicates it was dynamically loaded. Remember how we had our “magic string” import for a view in the view model? Here, we will export the dynamic view in the code behind. There is only one change to the auto-generated code behind file, and that is to add the Export tag:

[Export("DynamicView")]
public partial class DynamicView : UserControl
{
    public DynamicView()
    {
        InitializeComponent();
    }
}

That’s it for the view model and the views!

Providing Exports

The exports can obviously be supplied in a variety of ways. For this example, I simply created a class and exported a few values to demonstrate that the imports were working and merging with the main list:

public class MoreStuffExports
{        
    [Export("MoreStuff")]
    public string Item1
    {
        get { return "MEF Export 1"; }
    }

    [Export("MoreStuff")]
    public string Item2
    {
        get { return "MEF Export 2"; }
    }            
}

The MEF Module Initializer

Now it’s time to wire everything together. There is actually almost nothing to the module initializer class. Because we base it on the PartModule we defined in the last post, the MEF-specific actions happen as part of the base class. In this class, we simply register the main view:

public class MEFInit : PartModule
{
    IRegionManager _regionManager;

    public MEFInit(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    #region IModule Members

    public override void Initialize()
    {
        base.Initialize(); // gotta call base for the MEF magic to happen
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(MoreStuffView));
    }

    #endregion
}

That’s it!

Conclusion

The goal of this this small series is to demonstrate how well PRISM and MEF work together, and how accessible modular and extensible applications can be in Silverlight 3. You’ve learned several ways to marry the view model to the view using different types of dependency injection containers and patterns. You’ve also seen how to take advantage of dynamically loaded modules to create application extensions that have an extremely small footprint but can easily integrate with the flexibility provided by both Unity and MEF in the context of PRISM.

Download the Source Code for this example

Jeremy Likness

PUT MICROSOFT AZURE TO WORK
We tackle the ongoing challenges of running in Azure.

We were one of the first Microsoft Cloud Solution Providers (CSPs), we are Cloud OS Network (COSN) certified with many production environments on the Microsoft Cloud Platform including Azure Certified for Hybrid deployments leveraging private and public clouds.

We know how to make Azure work for you.


Architected to
meet your needs.

Deployed
flawlessly.

Operated reliably
24x7x365.

We build solutions to address your individual business objectives with an eye to sustained technology innovation.

We manage the entire lifecycle from start to finish to ensure no surprises and allow you to focus on your business.

We only engineer and deploy environments which can be managed and maintained for you by our team of experts 24x7x365.

20 years of experience makes us a trusted partner you can count on.

We have developed a core methodology to ensure we accurately capture your needs and translate them into the best solution possible. This process gives you the peace of mind that your cloud investment will be aligned with the return you seek. We can be counted on to bring our industry experience and real-world best practices to operate Azure environments.

Our methodology involves 4 steps:

Assess > Migrate > Re-Platform > Operate

Moving into the cloud is not a one time event. With every customer engagement, we deliver a structured approach as follows:

Assess:

Migrate:

Re-platform:

Operate:

Rely on our team to map your existing environment to a corresponding Azure cloud.

Easily move from your existing environment to a public or private Azure cloud.

Understand how to transform your applications to better take advantage of Azure capabilities.

Our team actively manages all maintenance and optimization to keep your environment running at its best.

Put Azure to Work

We know how to make Azure work for you.

LEARN MORE

Azure Environments Managed by Atmosera

We help you determine how best to run your applications in the deployment best suited for their unique requirements.

PUBLIC

HYBRID

PRIVATE

Run your business on the fastest growing public cloud.

Run your apps in the environment best suited for their requirements.

Run your business using a private and hosted Azure cloud.

Global Reach

More data centers than AWS & Google cloud combined

50

+$15B

6

Regions with 140 countries

Invested by Microsoft

Regions for US Government

The Power of Microsoft’s
Hybrid Platform

Azure Certified for
Hybrid Cloud

Microsoft is the only hyperscaler to offer a true hybrid solution with the flexibility to run applications using private or public clouds — and the ability to move between them.

Atmosera has the skills and expertise necessary to help you architect, deploy and operate integrated hybrid cloud solutions based on Microsoft’s Azure stack and microservices.

Atmosera has developed core competencies and intellectual property to take full advantage of all Azure has to offer.

All Atmosera Azure services receive the “Azure Certified for Hybrid Cloud” designation which confirms it passed Microsoft’s rigorous validation process under the Cloud OS Network (COSN) program. Customers benefit from knowing that their solution was carefully planned and executed using best practices and proven methods.

Not Sure How to Get Started?

Atmosera Azure pre-configured solutions can help.

We find many customers are not sure how to get started.
We developed a series of pre-configured solutions around specific use cases common for many customers.
You can take advantage of thoroughly tested and optimized solutions and accelerate the return on your cloud investment.

We deliver solutions that accelerate the value of Azure.

Ready to experience the full power of Microsoft Azure?

Start Today

Blog Home

Stay Connected

Upcoming Events

All Events