Uwp IoC Support

I have been developing UWP applications for a few years now and I truly enjoy it. It’s been the platform where I experiment with and used it to learn a lot about programming.

In my day job I develop web applications on the ASP.NET MVC framework and one of the things it does right is the native support for IoC containers out of the box.

When a HTTP request arrives to an action method in a controller, MVC will initialize the controller, inject all dependencies in its constructor and have it ready to handle the request.

I find MVC and MVVM to be comparable as a software architectures. However, the support for IoC Containers in Microsoft’s UWP platform is surprisingly lacking. When navigating to a new page in UWP you are forced to manually initialize the view model and provide all the required dependencies to it.

There is no native support in UWP for developers to bring in an IoC container and have it inject dependencies in the page constructor.

This has always been annoying for me personally and when I tried to find a workaround this, it seemed the most popular solution was to rely on the Service Locator pattern in the form of a ViewModel locator.

Some people consider the Service Locator to be an anti-pattern. I agree with that, but UWP seems to be forcing us to go down that path.

Recently I had an idea to overcome this limitation and it has worked surprisingly well at least for me. So this post is an invite for other UWP developers to look at this solution, use it, evalaute it, and decide if it is a better replacement for service locators in UWP.

How does it work?

It works by providing a modified Frame class that provides a custom handler for the Navigated event. In the custom handler, this frame attempts to perform a property injection on the new page before the page instance is loaded and displayed.

I have packaged up this solution in a nuget package. It is still a pre-release at version 1.0.0-alpha.

How to use it?

Setup

Start by installing the nuget package in the UWP application:

Install-Package UWPIoC -Version 1.0.0-alpha01

… and then make the App.Xaml.cs look like this:

public static Host ApplicationHost; // (1)

/* ... */

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    IServiceProvider serviceProvider = /* ... */ // (2)
    ApplicationHost = new Host(serviceProvider);

    var rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        rootFrame = ApplicationHost.CreateNewHostedUwpFrame(); // (3)

        /* ... */

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    /* ... */
}

Here’s what the code above is doing:

(1) Initializes a new instance of the Host class. This class holds a reference to a IServiceProvider instance and Frame instance.

(2) Depending on what IoC container being used, this line gets a reference to its service provider which is used by IoCFrame.

(3) Requests a new instance of IoCFrame from the Host instance. This is done when the window has no current frame instance (this is always true when the app has just been launched).

Now, whenever a call is made to Frame.Navigate from any page, the IoCFrame will take care of injecting the new page dependencies.

Dependency Injection in pages

So how does a page code-behind file looks like when using IoCFrame to inject properties?

Here’s an example:

public sealed partial class MyPage : Page
{
    [ViewModel] // (1)
    public MyPageViewModel ViewModel { get; set; }

    [Dependency] // (2)
    public ILogger<MyPage> Logger { get; set; }

    public MyPage()
    {
        /* ... */
    }

    /* ... */
}

That’s it! Really. That’s all there is to it!

Here’s what’s going on in this snippet:

(1) This the public auto-property holding a reference to a view model instance. the [ViewModel] attribute tells the IoCFrame this is a view model and that it should manually construct an instance because it won’t be registered in the IoC container. IoCFrame will use a bit of reflection to find the view model’s dependencies, request them from the IoC container and then create the instance.

(2) The [Dependency] attribute tells the IoCFrame that this is a typical service/dependency that is registered in the IoC container. IoCFrame will then request an instance of this service type from the IoC container and inject it in this property.

As you can see, the constructor has no custom code, no additional work from you as a developer is required here.

Now, when some code makes a call to Frame.Navigate(typeof(MyPage)) the app will navigate to the new page, and all of its dependencies will be there and ready to be used as expected.

Conclusion

While this is still not constructor injection, I’d say that in this case, property injection still works just fine and allows you as a developer to focus on building good UI/UX rather than writing biolerplate code for every new page you create to get instances of services/ViewModels you need.