共用方式為


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 (https://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

  • Anonymous
    April 27, 2013
    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?

  • Anonymous
    April 29, 2013
    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.

  • Anonymous
    April 29, 2013
    Thanks Francis.  I had two constructors in MainPageViewModel.  It worked once deleted. Thanks again and keep up the good work on this series.

  • Anonymous
    May 14, 2013
    The comment has been removed

  • Anonymous
    May 14, 2013
    Terrence: Did you complete step #3 above, overriding the MvvmAppBase Resolve method?

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

  • Anonymous
    May 14, 2013
    The resolve method is being called from the SetAutoWireViewModel Method

  • Anonymous
    May 14, 2013
    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); }

  • Anonymous
    May 14, 2013
    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.

  • Anonymous
    May 14, 2013
    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); }

  • Anonymous
    May 14, 2013
    In your case it will be: protected override object Resolve(Type type) {   return this.DIContainer.Resolve(type); }

  • Anonymous
    May 14, 2013
    That is right, I remember you changing that in the video.  Thank you for your help.