Prism for Windows Runtime: Integrating a Dependency Injection Container


This is the fourth post in a series that walk you through creating a simple Windows Store app using the Prism for Windows Runtime library. Please review the third post in the series for the steps necessary to create the basic MVVM style app based on MvvmAppBase.

You can get the latest source on CodePlex.

The following procedure shows how to integrate a dependency injection container into a Windows Store app that leverages MvvmAppBase from the Microsoft.Practices.Prism.StoreApps library.

  1. Add a reference to a Dependency Injection Container library. This walk through will use the Unity v3 container which is available via nugget (http://www.nuget.org/packages/Unity/).
  2. Add a private member varliable to the App class that will hold the container.
    private UnityContainer _container = new UnityContainer();
  3. Override the Resolve method on the App class so that it uses the container to resolve object instances from a type.
    protected override object Resolve(Type type)
    {
        return _container.Resolve(type);
    }
  4. You can now remove the call to ViewModelLocator.Register in App.OnInitialize because the ViewModelLocator can use the container to resolve view model types. Register into the container any services that will need to be provided to view models via constructor injection. The StartPageViewModel needs an instance of IFlyoutService. The following code registers the three services provided by the MvvmAppBase.
    protected override void OnInitialize(IActivatedEventArgs args)
    {
        _container.RegisterInstance(NavigationService);
        _container.RegisterInstance(FlyoutService);
        _container.RegisterInstance(SessionStateService);
    }
  5. Run the app. Notice that the button still causes the FlyoutService to show the SignInFlyout.

Comments (12)

  1. shaggygi says:

    Great series.  I get an error when trying this step.

    Resolution of the dependency failed, type = "MyTestApp.ViewModels.MainPageViewModel", name = "(none)".

    What did I miss?

  2. Did you complete step #4? The OnInitialize override should include a registration into the container of the FlyoutService which implements IFlyoutService. This should be the only constructor dependency for MainPageViewModel.

  3. shaggygi says:

    Thanks Francis.  I had two constructors in MainPageViewModel.  It worked once deleted.

    Thanks again and keep up the good work on this series.

  4. Terrence says:

    After removing the ViewModelLocator.Register line from the OnInitialize and adding the container.RegisterInstance(FlyoutService), it crashes, wanting the default constructor for the StartPageViewModel.

  5. Terrence: Did you complete step #3 above, overriding the MvvmAppBase Resolve method?

  6. Terrence says:

    Yes, in fact it is blowing on the Reslove method, it can't resolve StartPageViewModel because there is no paraless ctor.

  7. Terrence says:

    The resolve method is being called from the SetAutoWireViewModel Method

  8. Terrence says:

    protected override void OnInitialize(IActivatedEventArgs args)

    {

    base.OnInitialize(args);

    //ViewModelLocator.Register(typeof(StartPage).ToString(), () => new StartPageViewModel(FlyoutService));

    this.DIContainer.RegisterInstance(FlyoutService);

    }

    protected override object Resolve(Type type)

    {

    return base.Resolve(type);

    }

  9. Your App.Xaml.cs, which I assume derives from MvvmAppBase, has an override of the Resolve method that should use the Unity DI container to perform the resolution. If your overridden Resolve method simply calls base.Resolve, you will get an exception because the MvvmAppBase will by default use Activator.CreateInstance. If you use the Unity container to resolve, the constructor parameters will be resolved by the container.

  10. 3.Override the Resolve method on the App class so that it uses the container to resolve object instances from a type.

    protected override object Resolve(Type type)

    {

       return _container.Resolve(type);

    }

  11. In your case it will be:

    protected override object Resolve(Type type)

    {

      return this.DIContainer.Resolve(type);

    }

  12. Terrence says:

    That is right, I remember you changing that in the video.  Thank you for your help.