Tuesday 22 April 2008

MVC Architecting Silverlight Applications Part 1 - M-V-VM

In my previous post I mentioned that I had used the Model-View-ViewModel approach to building WPF applications.

In this series of blog posts I will describe this pattern, and show you how to build a small sample application using it within the context of Silverlight. I have folded a bunch of base classes and helper classes into my open source Silverstone framework and these will be used extensively.

What is Model-View-ViewModel

I am assuming that those of you reading this post are familiar with the Model View Controller pattern and have probably used it in some form of ASP.NET or WinForms application. If not then you might want to check out Martin Fowler's article on GUI Architectures for an in depth technical appraisal, or this page on the MSDN site for more information.

The Model-View-ViewModel (or MVVM) pattern is a form of MVC specifically catered for scenarios where you have a very strong data binding ability within the framework, and also one where you want to give your designers the freedom to design the view completely themselves.

Let's explain the three components now:

Model - The Models are the classes which represent the domain on which the application is processing/interacting with. I often refer to these as DataModels, as they are modelling the data in the application, and usually contain some kind of business rules and validation logic.

View - The Views are simply the classes which the render the graphical elements to the user and allow him to interact with the application. They are ideally implemented in 100% markup, although in practise there will end up being some code there too!

ViewModel - The ViewModels are the new kids in town for those of you familiar with traditional MVC/MVP. They essentially take the part of the controller or presenter, and are named as such because they "model the view". Each ViewModel is therefore built for a specific View, and contains all the data and behaviour logic which that View requires to interact with the data models.

Why "ViewModel"?

In an MVC application, the Controller will typically respond to an event when notified by the view, such as a "Save" button being clicked. It will usually then interact with the model in some way, e.g. reading some values from the view and applying them to the model. Finally it will notify the view of something. For example, it may tell it to display a "your model was saved" message to the user, or alternatively to display a validation warning if something went wrong.

The ViewModel has the same responsibility as the controller, but it handles that responsibility in a different way. Firstly, it makes use of the rich binding provided by the platform by exposing data to the View and raising property changed notifications when that data changes. It also expects the view to use two way binding to push changes direcly back to those properties. Only the data which is required for that specific view is exposed. This will generally include the models which the user needs to view or edit as well as controlling properties which tell the view which state it is in. For example the ViewModel may expose a boolean property which tells the view that it is in the process of saving the DataModel.

At the same time, the ViewModel exposes Commands for the View to execute. It does so in such a way that the commands can be bound directly to UI elements (such as buttons). It is the commands which are responsible for handling user interactions. For example , a save command may be exposed which saves whichever changes users have made to the data models. See my previous blog post for more information on Commands in Silverlight

In Silverlight and WPF terms, the important point to take home is that the ViewModel is the DataContext of the View. This is the key enabler of all the data binding I have been referring to!

And that's really it for now. I hope this makes sense a summary for the architecture pattern we are trying to follow. If you have any questions please let me know.

In the next part of this series, I will begin walking through how to develop a small application using this pattern under Silverlight.

Have a great day!

Neil

Sunday 13 April 2008

A basic IoC container for Silverlight

All the recent User Interfaces I have built have been developed using some kind of MVC approach - be it the good old MVP (Model/View/Presenter) pattern for WebForms applications, or the recently devised MVVM (Model/View/ViewModel) pattern for WPF.

Well I recently started work on a small "pet project" using Silverlight (let's just assume for those who know me that the aforementioned pet is a Horse) and some of my development seems to have been spent building shared components which could be used in other projects. For example, I have previously blogged about my Command Implementation for Silverlight which I am using in this project.

When building MVC applications, a key piece of the developer's strategy is the ability to abstract a class's dependencies into an external component which will resolve those dependencies at runtime into what is required by the application. This allows (for one thing) the developer to build each class without worrying too much about where that class obtains its dependencies from. Note that classes which resolve other class's dependencies at runtime (a technique known as Dependency Injection) are commonly known as Inversion of Control containers. I won't get into much more detail about this here and recommend reading this excellent MSDN article.

So, despite previous attempts to cross-compile the excellent Ninject IoC framework into Silverlight (see this blog post and comments) I failed to get it to run. The problem is that Silverlight implements a new security model, in which lots of framework methods (such as some of System.Reflection.Emit, and System.Threading.StackTrace) are not allowed to be executed from application code. Essentially, if you look in Reflector at the Silverlight libraries, anything marked with a [SecurityCritical] attribute will be inaccessible to any code you write. If you are interested, you can get more information about Silverlight's new security model here. Personally, I think it's a little overzealous, and I hope the restriction will be lifted somewhat as Silverlight's deployment mechanism matures - I'm not sure how it would work but I'd like to see shared libraries being built which are able to call into some of the code deemed critical. I guess that's not my call though!

Anyway, given that no container I could find out there would run on Silverlight, I set about writing my own IoC container to "free myself" from my dependencies, so to speak. I pushed my code into a small library I have named Silverstone. You can download the DLL here.

The container is implemented as a very simple static class - Silverstone.DI.IocContainer. What I am currently doing is just registering all my dependencies in the Startup method of my App.xaml.cs, as follows:

using Silverstone.DI;

public partial class App : Application
{
  public void Application_Startup(object sender, StartupEventArgs e)
  {
    // Register an instance of a concrete type MyClass against interface IMyInterface.
    // The instance will be passed to all constructors with parameter of type
    // IMyInterface and all settable properties of type IMyInterface.
    IocContainer.RegisterInstance<IMyInterface>(new MyClass());

    // Register a concrete type against an abstract type.  This means that a new
    // instance of the concrete type will be created every time the abstract type is
    // requested by either a constructor with parameter of type IMyInterface or a
    // settable property of type IMyInterface.
    IocContainer.RegisterForCreation<MyClass, IMyInterface>();
  }
}

That's pretty simple really! Note that you can only register the same abstract type (IMyInterface in this example) once.

When you wish to retrieve the implementation of any abstract type, it's just a simple call to Get<>();

  IocContainer.Get<IMyInterface>();

Assuming that MyClass had been registered against IMyInterface in the container, the above call would actually return an instance of MyClass. Otherwise it will return null.

That's all there is to it really! Of course, the container is iterative and will walk the tree of constructors and properties on all objects as it goes. So, for example, if MyClass has a constructor with a parameter of type IMyOtherInterface, that will be requested from the container when creating the instance of MyClass. This is where the power of a container comes in - when you don't have think about all the dependencies of the dependencies of your dependencies, you can think a lot more clearly!

If anyone starts using this stuff and has any feedback, please let me know. Alternatively you can take a look at the source code which is available on the Google Code site for the project.

Have a great day

Neil