Silverlight

Dependency Injection, MVVM, Ninject and Silverlight

Intro

The MVVM patterns is pretty popular these days. In Silverlight and WPF it is used a lot. Dependency Injection is also used very often. In this tutorials I would like to show you how to use Dependency Injection when building a Silverlight application using the MVVM pattern.

There are numerous Dependency Injection Frameworks. For this tutorial I’ve chosen Ninject. The main idea on how to implement DI in your application is pretty much the same for all frameworks. In this tutorial I hope I can give you a small introduction in using Ninject in you projects.

Ninject is an open source project which can be found at www.ninject.org. Ninject is also available through the NuGet tool in Visual Studio. Have look at my NuGet tutorial on how to get it through that.

Demo project

The demo project is a very simple game. The objective of the game is to guess a number. There will be a web service that can be requested to provide a random number. The game consists of three screens or Views. The first, StartView, asks the player for the maximum number. The second screen, GameView, ask the player to guess a number between 0 and the maximum number given on the first screen. The last screen, ResultView, shows whether the guess number equals the randomly chosen number and provides the user with two options, try again or restart. These views are displayed inside a fourth view, ShellView, that handles the navigation.

Each view contains one or more commands and one or more properties to handle interaction with the user. The views contain only the most basic controls to interact. On the StartView there’s a textbox to set the maximum number to guess for and a button to start playing. The GameView contains a textbox to get the guess from the user and a button that triggers navigation to the ResultView. The ResultView contains a styled checkbox to show if the guess was correct and two buttons. One to navigate to the GameView, to try guessing again, and one to navigate to the StartView, to start the game all over.

The generation of a random number takes place on the server. A proxy class is placed between the calls to the service and the caller of the methods. This implementation of the custom IProxyService interface will be replaced when unit testing to be able to use a dummy implementation.

The navigation works by calling a method on shared class between the viewmodels.The INavigator interface contains the method. It also contains an event the ShellViewModel is listening to. Calling the method would fire the event and causes the ShellViewModel to update the visible view.

Setup the IOC

Ninject uses a Kernel to setup the Inversion of Control, or IOC, container. The IOC container is filled with classes and interfaces that go together. We the program asks the Kernel for a specific type, this will be returned by the container. By default you can instantiate the StandardKernel class. The constructor of the StandardKernel class takes a NinjectModule as a parameter.

To separate the construction of the Module and the construction of the Kernel, the NumberGameModule class is created. The class inherits from the NinjectModule class. It has to implement the abstract Load method.

private IKernel Kernel;
...
Kernel =
    new StandardKernel(new NumberGameModule());

The binding of classes together for the IOC container happens in the Load method of the NumberGameModule class. The method is called automatically when the Kernel is created.

public class NumberGameModule : NinjectModule
{
    public override void Load()
    {
        //todo: Inititialize the IOC.
    }
}

Often an interface is bound to a class that implements that interface. This way alternative uses of that interface can be used if needed, when Unit Testing for example. The binding uses a fluent syntax and looks like this:

this.Bind<IServiceProxy>().To<ServiceProxy>();

This literally Binds the IServiceProxy interface To the ServiceProxy class. This means that every time you need a ServiceProxy you call the Get method on the kernel, like this:

kernel.Get<IServiceProxy>();

In this case the kernel instantiates a new ServiceProxy for you. If, in case of testing for example, you bind a TestServiceProxy to the IServiceProxy interface. The TestServiceProxy will be returned, without changing the call to the Get method. In the next section you will see the true power of this.

Sometimes you don’t want to use an interface for a class. You just want to have an instance when asking for it. In situations like this you can bind a class to itself. The syntax for this is straight forward again:

this.Bind<GameViewModel>().ToSelf();

This sounds pretty useless, but to get all the nice features of dependency injection you’ll have to let the framework instantiate your classes, and never use the new keyword.

Lifetime

One of these features is using singletons. There a lot’s of reasons not to use the singleton pattern, they are hell to unit test for example. When using dependency injection you can have the framework manage the singletons. Which means that every time you ask the kernel to give you a specific type, you always get the same instance. But, in case of unit testing you can have it return a new instance every time. Without any changes to the code under test. For example, say you want to bind the INavigator interface to the Navigator class using a Singleton scope:

this.Bind<INavigator>().To<Navigator>()
    .InSingletonScope();

Without specifying a scope the InTransientScope() variation is used. If you need it, you can also have Ninject instantiate a new instance once every thread by using the InThreadScope() method.

Context

Often you find the need to use different implementations of classes in different contexts. For example, when using Expression Blend to create your views. You don’t want to call web services and do complex calculations, but only a simple implementation to work with. You can have Ninject create different instances based on the context. In this example the normal implementation is created in Singleton scope. When using this class in a designer, like Blend, a new instance is created on every call. A delegate method is used. The method should return a boolean. In the example below a lambda is used to shorten the syntax.

bool designContext =
    DesignerProperties.GetIsInDesignMode(
        App.Current.RootVisual);

this.Bind<IGame>()
    .To<Game>()
    .When(x => !designContext)
    .InSingletonScope();

this.Bind<IGame>()
    .To<AlternativeGame>()
    .When(x => designContext);

 

Constructor Injection

When having Ninject instantiate your classes Ninject automatically resolves the parameters of the constructor. This means that if your constructor takes two interfaces and Ninject knows how to resolve these, the implementation of the interfaces is injected into the constructor. For example, the constructor of the ResultViewModel takes two parameters. The IGame interface and the INavigator interface. Both these interfaces are known to Ninject and therefore can be resolved when a ResultViewModel is created.

public ResultViewModel(IGame game,
                       INavigator navigator)
{
...
}

Without using Dependency Injection you probably would new a game and a navigator inside the constructor, and thus create a dependency on these classes. When using injection you only have a dependency on an interface, and can use different implementations when needed. Which makes testing a lot easier.

There are occasions however where you want to have control over which constructor is used for injection. Ninject looks for the constructor that takes the most known parameters and tries to use that when resolving the class. If it can’t find any it will use the default parameterless constructor.  You can mark a constructor with the Inject attribute to force Ninject to use that one when resolving. Marking multiple constructors with the attribute will result in an exception. 

Binding the VM to the V

The last step would be to glue it all together. The kernel must be build and filled somewhere, and the viewmodels must be bound to the Views somehow. To do all this one could use the View Model Locator pattern. The ViewModelLocator class contains properties that represent the viewmodels used. The class has a static constructor so it can be constructed in Xaml. By doing this the ViewModelLocator can be defined a resource and be used throughout the application. The implementation of the constructor is described earlier. Only a null-check is added. The ViewModelLocator looks like this:

public class ViewModelLocator
{
    public ShellViewModel ShellViewModel
    {
        get {
            return Kernel.Get<ShellViewModel>();
        }
    }

    // other ViewModels are defined
    // the same way.

    private static readonly IKernel Kernel;

    static ViewModelLocator()
    {
        if (Kernel == null)
        {
            Kernel = new StandardKernel(
                new NumberGameModule());
        }
    }
}

To get the ViewModelLocator known in Xaml you’ll have to define it as a resource. The best place to do this is directly in your App.xaml. In the Resources section define a new resource with and use a key like “ViewModelLocator”, like this:

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:Common="clr-namespace:NumberGame.Common"
  x:Class="NumberGame.App">

    <Application.Resources>
        <Common:ViewModelLocator
            x:Key="ViewModelLocator"/>
    </Application.Resources>
</Application>

When the application is started the resource is created, and the static constructor is executed. You can use the ViewModelLocator as a StaticResource now.

To get the right viewmodel in a view the DataContext of that particular view has to be bound to a property of the ViewModelLocator resource. In case of the ShellView you would like use the ShellViewModel property of the ViewModelLocator. Add a line like below to the definition of your view in xaml:

DataContext="{Binding ShellViewModel,
    Source={StaticResource ViewModelLocator}}"

All this is saying that you would like to set the path of the binding to the ShellViewModel property of the ViewModelLocator StaticResource.

 

Wrap up

There are a lot of situations where you might want to have Ninject do more than what is explained in this tutorial. Ninject can do a lot more, which is left out for the sake of simplicity. Sometimes you’ll need specific custom factory methods to create your objects or you might have separated your classes into a different assembly. Ninject can be used in situations like this too. If something isn’t supported right out of the box, Ninject is extensible and open source. 

You can find the demo project that goes with this tutorial here.

If you have any questions, suggestion or just want to leave a comment you can use the area below, feel free to send me an email or contact me through twitter. To be the first to know when there’s a new tutorial online you can also subscribe to the RSS feed.

3 comments

  1. Really good article(and example). I find Ninject very easy and intuitive and try to use it in almost every project. Very recently I have started developing Silverlight apps. Nice thing to take advantage of Ninject there as well.

  2. Thanks for the post Timmy. However, with what you’ve described, how do you address cases where one ViewModel may have an internal list of ViewModels that it creates on the fly? Would you just make your Kernel property public so that subsequent ViewModels could have access to it?

Leave a Reply

Seo wordpress plugin by www.seowizard.org.
%d bloggers like this: