Prism / Dependency Injection for Windows Phone 7

by 14. January 2011 23:42

If you are looking for Prism functionality for Windows Phone 7 you may want to visit our open source Password Manager application on CodePlex (http://PasswordMgr.CodePlex.com).

The objective of porting Prism to Windows Phone 7 was to provide a platform that can be used identically on Desktop, Silverlight and Windows Phone 7 operating systems so that I could have a single code base using the Project Linker (May 2010).   Since Prism is available for both Desktop and Silverlight all I had to be concerned with was  Windows Phone 7.   The Prism for Windows Phone RC on CodePlex lacked Dependency Injection support and only provided a few classes - this was not going to do for our purposes.

Important note: Our primary goal is to create a single code base that supports multiple platforms.  Our efforts with porting Prism 4 and Unity to the phone platform will be limited to this objective; we will not be investing time/energy into building up the Unity feature set beyond our needs as this time is needed to complete the framework and Password Manager application.

A key component that I was missing was Unity, a Dependency Injection (DI) container that Prism 4 is designed to work with (as well as MEF).  Without this DI container there would be no port (MEF is not supported on both Silverlight and WP7 so this was not an option).  Since the latest word on Unity for WP7 was "there would be no port" I had to improvise.  I grabbed the Container Model, DI container, from the Mobile Application Blocks and imported it into my Gwn.ContainerModel.Mobile (WP7 project). 

Unit Testing

It was time to roll up my sleeves and port over all of the Prism and Container Model unit test, this posed a unique problems since I needed the test to run against the Windows Phone 7 code, not the desktop code.   My solution is shown in Fig 1. below:

  1. I copied Prism.Desktop files into Gwn.Prism4.Mobile (two left panes below)
  2. I copied Prism.UnityExtensions.Desktop into Gwn.Prism4.Mobile\UnityExtensions folder so I didn't have to manage two projects.
  3. I created a Gwn.Prism4.Desktop project that was linked to the Gwn.Prism4.Mobile project (two middle panes below).
  4. I created my Gwn.Prism4.Desktop.Tests and pointed it to my linked code in Gwn.Prism4.Desktop (code resides in Gwn.Prism4.Mobile).
  5. I followed the same steps for the Gwn.ContainerModel.Desktop.Tests

I was starting this port under the notion "if it compiles, it will run".

Emulating Unity with the ContainerModel

Getting Prism 4 to compile required us to provide components it needed, such as ObjectBuilder2, ServiceLocation and Unity classes. As the compiler complained I would pull the classes from the applicable source and place it in a folder, within the Gwn.ContainerModel.Mobile project, that corresponded with the namespace. When the smoke settled I was pleasantly surprised that most of the Prism 4 framework remained and compiled successfully.

There were some component methods, such as RemoveAll() in the image below, that I had to create because they didn't exist in the .Net WP7 environment. Since the unit test were running against the ported code I had a reasonable amount of confidence that if the unit test passed that my manual updates were successful.

 As of changeset 81886, of the Password Manager on CodePlex, there are 727 test that successfully pass against the original Prism4/ContainerModel test fixtures.   As is the goal with Test Driven Development (TDD) I had a lot of failing test that I needed to make work.   Most of the test revolved around the Unity container; up to this point I was only concerned with getting it to compile so along the way I created a UnityContainer class (that implements IUnityContainer) which had a lot of empty methods that simply threw exceptions.   You'll find that there are still empty methods in the UnityContainer because I only concerned myself with the methods that were required to pass the unit test.

I started by instantiating the ContainerModel DI container on line 11 (which was passing all of it's unit test) and then updated each called method to utilize the _container class.    I then had to update each failing method to perform the functionality that was required to successfully pass the test (reference RegisterType method below).

Along the way I found there were a number of null references because the ContainerModel DI container does not support constructor injection.  This required me to update each Prism 4 class that relied on constructor injection to ensure each constructor parameter was supported with setter injection;  I moved each parameter into a property with a [Dependency] attribute above it.   I then had to update the Resolve methods to ensure that as each class was resolved that it performed a BuildUp() which ensured its properties, marked with the DependencyAttribute, were initialized.

Notice

Blog videos and references to CodePlex projects are no longer valid