Showing posts with label MEF. Show all posts
Showing posts with label MEF. Show all posts

Tuesday, 2 March 2010

MEFfing up a MVVM/CSLA example (Part 2)

In Part 1, we created all the necessary groundwork for a (simple) MVVM/CSLA implementation using MEF. In summary we created:

  • The Model interfaces & classes (ITelephoneList, TelephoneList and TelephoneInfo).
  • Interfaces for our View and ViewModel classes (ITelephonesView and ITelephonesViewModel).
  • A concrete ViewModel class(TelephonesViewModel).
  • A base and concrete ViewModelLocator class (ViewModelLocatorBase and TelephonesViewModelLocator respectively).
  • Imported the CompositionHost and PartInitializer classes to extend MEF support for WPF.

OK now I remember...

Lets move to the View. Add a UserControl (TelephonesView) with the following XAML:



And in the code-behind:



The view exports itself as an ITelephonesView type. When MEF resolves a new instance, a new instance of TelephonesViewModelLocator will be created. At runtime, the locator will satisfy all its imports, which includes the ViewModel of type ITelephonesViewModel, allowing the View to use it as the DataContext and access its Model (which will also be resolved by MEF by injecting the Model's factory into the ViewModel's ImportingConstructor decorated constructor).

Creating the shell

For this example, the shell will ask MEF to import a ITelephonesView part and export itself as a Shell type. The XAML:



And the codebehind:



And finally, the ViewModel of our shell:



OK I am bored now...

We are nearly there. The last thing we need to do is setup (bootstrap?) MEF. We do this in the App.xaml.cs code-behind:



If you now launch your application, MEF should setup its container and resolve a new instance of the TelephonesView, satisfying all the dependencies as described above and adding it in your Shell's StackPanel. Also, if you open TelephonesView in either Blend or the VS designer surface, you should get everything rendering just fine.

Aftermath

This example is quite a simplified one so any conclusions should be taken with a punch of salt. There are certain things that I like about this MEF approach. Defining imports/exports feels more natural than injecting instances in different classes, since the "chaining" of object creation is awesome and can be extended a lot. On the other hand, the fact that an extra base class (ViewModelLocatorBase and n ViewModelLocator classes really spoilt the picture for me. Of course, this is not a MEF shortcoming but mine, though I could not figure a way around not having the locator classes.

For now though, I don't envisage using this pattern. It will be interesting to see what the next drop of Composite WPF will bring as far as MEF is concerned and then would be a good time to revisit.

Monday, 15 February 2010

MEFfing up a MVVM/CSLA example (Part 1)

MEF appears set to be the next big player in the .Net toolset. The next drop of PRISM looks like it will integrate MEF more, making the question of when to use an IoC and when to use MEF all the more unclear. A quick search with Google or StackOverflow returns many results but here is one that summarizes it quite well.

So it would look like in an MVVM scenario, the IoC approach is more appropriate. But I wanted to see the difference in action, in order to compare results. So lets see one possible way of building a View and associating a ViewModel and Model using MEF and how it fares against a possible IoC approach.

Requirements

For this test I set out the following requirements:

  • Start building the chain of objects (parts) using View first.
  • Use interfaces throughout.
  • Make the view Blendable.

So the idea is that our main Window will import a UserControl, the UserControl will import the ViewModel and the ViewModel imports the model.

Setting everything up

First, lets create a simple CSLA readonly list to serve as out Model. Notice that what is exported is a factory delegate rather than the type itself (just one way of doing this), an idea inspired by a question asked at StackOverflow:



On the UI side, the contracts for the View and the ViewModel:



The implementation of the ViewModel:



A couple of things to note here. First, the way we load the model using the imported factory (similar idea used in a previous IoC example), asking MEF to use the constructor with the import by attributing it with ImportingConstructor. The second thing is the default constructor. If that was not in place, we would not have a fully blendable view. I will explain this more later but for now just remember that the Model will need to be loaded properly in the default constructor and this is done purely for design time convenience.

Where it starts to get a bit ugly.

At this point, we need to somehow import an instance of the ViewModel into our View (in XAML), which first needs to import the TelephoneList factory. It appears some functionality to facilitate and improve this process is in the pipeline for MEF, but for now the best approach I could come up with is to use a locator (idea inspired by this blog post). The locator will return a ViewModel instance depending on the mode (design or runtime) we are currently in. The full source of this class is:



This allows us to extend the locator class once per ViewModel (the ugly bit) but also let us import the instance at runtime or create a "dummy" instance at design time (the nice bit). Following from where we left the example, the implementation of an ITelephonesViewModel locator would look like this:



Where is PartInitializer?

Not sure if I mentioned this thus far, but the example was build in WPF (I am going completely SL when VS2010 and SL4 are properly released!). But the latest release of MEF for the desktop does not contain the PartInitializer class so what happened here?

It turns out that Glenn Block provided a desktop implementation. You can download the sample solution and include the required files (CompositionHost.cs and PartInitializer.cs) in your solution. Not sure if this will eventually be introduced in MEF but it works fine nevertheless.

And at this point I will leave you on a cliffhanger ending. The post is quite long so will break it in 2 parts. In Part 2 we will get a complete working example and compare it with the more "traditional" IoC approach.