Silverlight 4, MEF and MVVM: EventAggregator, ImportingConstructor and Unit Tests

I had recently the possibility to use MEF and Silverlight in a sample project together with Prism, this is for sure a great combination of frameworks for bulding applications using maintainable and extensible code. I don’t think that using MEF excludes the usage of Prism and vice versa,  the choice should be pondered and analyzed accordingly to the problem to solve.

Starting from the previous experiments, I decided to refactor and cleanup the MVVM approach in order to:

  • obtain simpler code;
  • inserting an EventAggregator managed by MEF to exchange messages;
  • maintaining the Visual Studio designer/Blend support;
  • trying a simple unit test using the framework available in the Silverlight Toolkit.
  1. Using the EventAggregator

The first step is inserting in the project the Prism EventAggregator downloading the “Microsoft.Practices.Composite.dll” and “Microsoft.Practices.Composite.Presentation.dll” libraries from the Prism site on Codeplex.

It’s now possible to make available in the application an instance of it using this syntax:

public class EventAggregatorProvider
   public IEventAggregator eventAggregator { get { return new EventAggregator(); } }

In this way we are able to import it in the ViewModel class using an [ImportingConstructor] attribute:

public MainPageViewModel(IEventAggregator eventAggregator, IDataItemsService dataItemsService)
   _eventAggregator = eventAggregator;
   _dataItemsService = dataItemsService;

When an [ImportingConstructor] is found, MEF looks for an [Export] for each parameter available in the constructor, in this case we must have exported an “IEventAggregator” and an “IDataItemsService”.

We are now able to access the instance of the EventAggregator and Publish/Subscribe to events using a syntax like:

//Call the Service

//Subscribe to the "DataItemsReceivedEvent"

_eventAggregator. GetEvent(). Subscribe(
    dataItemsReceived =>
        this.dataItems = dataItemsReceived;

In this case we are receiving the result of the async calls via the EventAggregator and a DataItemsReceivedEvent:

public class DataItemsReceivedEvent : CompositePresentationEvent {  }

DataItemsService code publishing the Event:

//Initialize the collection
DataItemWcfService.DataItemServiceClient svc = new DataItemWcfService.DataItemServiceClient();
svc.GetDataItemsCompleted += (s1, e1) =>
    if (e1.Result != null)
        var dataItems = new DataItems();
        e1.Result.ToList().ForEach(d =>
            dataItems.Add(new DataItem() { Description = d.Description });

        //Publish the DataItems
        _eventAggregator. GetEvent(). Publish(dataItems);

        isLoading = false;
isLoading = true;

2. Maintaining the Visual Studio designer/Blend support

In the previous experiments I enabled design-time data by inserting a new ViewModel class which can create some confusion, so I decided to skip this step and using a unique ViewModel following this approach:

  • the ViewModel parameterless constuctor contains the initialization for data to be used during design time and tests;
  • the other constructor marked with the MEF [ImportingConstructor] attribute enables initialization of services and event aggregator.
public MainPageViewModel(IEventAggregator eventAggregator, IDataItemsService dataItemsService)
    _eventAggregator = eventAggregator;
    _dataItemsService = dataItemsService;

3 – Unit Test

To verify the approach described, I’ve inserted a new “Silverlight Unit Test project” to the solution (note that the “Silverlight Toolkit” must be installed to use this feature) and then a simple Test method containing the following code:

public class Tests
    [Description("Test the creation of a ViewModel and the initialization of Design/Test Data")]
    public void TestViewModelCreation()
        var vm = new MainPageViewModel();
        Assert.AreEqual(vm.dataItems.Count, 2);

Since MEF is only used to compose run-time Parts, I’m not using it in the Unit Tests.

So we have now a new piece of code, which I’ve called a “MEFModule” organized with a MVVM approach and ready for design-time support, unit tests and extensibility: ready to be inserted in a Navigation applicationdynamically loaded and enabled for design time using Blend Sample Data, stay tuned.

The source code is available for download here.

Happy Silverlighting!