Creating a Xamarin Forms App Part 5 : Dependency Injection

  • Part 1 : Introduction
  • Part 2 : Getting Started
  • Part 3 : How to use Xamarin Forms with Visual Studio without the Business Edition
  • Part 4 : Application Resources
  • Part 5 : Dependency Injection
  • Part 6 : View Model First Navigation
  • Part 7 : Unit Testing
  • Part 8 : Consuming a RESTful Web Service
  • Part 9 : Working with Alerts and Dialogs
  • Part 10 : Designing and Developing the User Interface
  • Part 11 : Updating to Xamarin Forms 1.3
  • Part 12 : Extending the User Interface

Why Dependency Injection?

Dependency Injection (DI) is a fundamental practice used to manage the dependences between application objects in medium to large-scale applications. Indeed small applications will also benefit from it. However, it is one of the most misused and misunderstood patterns around today. DI allows us to remove the responsibility of creating objects by those objects that are dependent on them. Indeed many of these objects may be shared by other objects and may also have dependencies of their own. This can cause a situation where you end up having to pass down objects deep into an object graph just so they can be use by an object further down. We can simply this by having a container where objects can be registered and resolved. This is known as the inversion of control (IoC). i.e. Control for creating objects has been inverted so they are created by an external source and then passed to objects. I don’t want to go to deep into this. There are plenty of resources out there on DI and IoC and I urge you to read up on this subject if you are unfamiliar with it.

Service Locator – The Anti-Pattern

There is also another pattern that is related to Dependency Injection called Service Location. This pattern also makes use of an IoC container to resolve objects and in some cases their dependencies. It is generally a static class that can be used within objects themselves to resolve objects they wish to use. This breaks the fundamental principle of DI where the responsibility for resolving objects should be completely removed from objects and any dependencies should be ‘injected’ into them. Service Location is actually an anti-pattern as it creates more problems than it solves. Using a service locator to resolve dependencies from within an object means that you are hiding the fact that there is a dependency. This has very undesirable consequences when you come to use that object then discover it throws an exception because one of it’s dependencies could not be found. There is no way of knowing without having an understanding of the internals of object, and which objects must be registered with the Service Locator container before you can make use of it.

The correct approach should be for its dependencies to be clearly advertised by its constructor. This then demands those dependencies are passed as parameters on order for the object to be created. This also helps enormously with unit testing. Without knowing of an object’s dependencies it is very likely that your tests are going to fail miserably. By taking the right approach and having those dependencies passed in to the constructor as interfaces we can mock the dependency objects in our tests. For simple applications this maybe fine, but generally I would advise against any form of service locator. More can be found on Service Locator as an Anti Pattern here.

 Xamarin Forms Dependency Service

Xamarin Forms provides an IoC container out of the box called DependencyService. Unfortunately this is not a Dependency Injection Container as the name suggests. It is a very simple Service Locator that allows us to register different implementations of an interface for each target platform so that we can make use of the correct one depending on the platform. It’s great that the Xamarin Forms team thought to include this but unfortunately it suffers from the same Service Location problems. Further more, it also makes use of a Dependency attribute that must be placed above the implementing class. This tightly couples that implementation to the DI framework being used. This is a bad thing. As your application grows it may be appropriate to switch to a better DI container. You’re then going to have to go through every implementing class and remove all those attributes and DependencyService calls. Ok, no big deal you might think, but better to be avoided. So I would not recommend using the built in DependencyService and instead seek to use one of the many readily available DI frameworks that are available through NuGet.

Which DI should I use?

There are already many mono versions available through NuGet. Personally I have used Unity and Autofac, but you can chose others if you feel more comfortable with them. However, there is another very important aspect to DI that you should consider, and as I said earlier is the cause of much DI misuse. Let’s take Unity as an example. Unity works well if used correctly, but it also suffers from what I’d describe as a DI/ServiceLocator hybrid. It allows you to pass the container around in your application so that it can be used from within your classes to resolve its dependencies. A classic example of this is where you have a class that has a collection that it needs to add items to. And those items themselves have dependencies of their own. The number of those items is dynamic and can only be determined at runtime. I have so often seen the DI container passed to the parent object as a dependency so that it can be used to resolve its child items at runtime. The DI container has now become a Service Locator. This however is unnecessary and can be dealt with in a much more elegant way. Some DI frameworks do this by enforcing that the container cannot be accessed once you have registered and built it.

One such DI framework is Autofac which takes a much more pure approach to DI than Unity. It also, in my opinion, has a much cleaner fluent API to work with. So how does it deal with the example above and create objects that need to be resolved within a parent object at runtime.

The answer lies in it’s name Autofac (Auto Factory), and the use of Func<Tin…, Tout>. This acts as an auto dependency resolver factory. All you need to do is declare a Func<> constructor argument where the out type is the type of the object you wish to resolve, and in types can also be defined if the dependency object requires parameters that are not registered with the container. (e.g. a Model object). We can declare a constructor something like this.

public ParentViewModel(Func<ItemModel, ItemViewModel> itemFactory)

And use it like this.

itemFactory(model);

The beauty of this is that it is now clear from the constructor that the ParentViewModel requires some function that expects an ItemModel and returns an ItemViewModel.

I have therefore chosen to use Autofac for Dependency Injection in my application. Autofac is also surprisingly very lightweight which makes it suitable for mobile development and can be easily added via NuGet. For more information about Autofac please take a look at the documentation here.

So, let’s get started.

I am going to change the main page so that it displays a list of mountain areas. These mountain areas are going to come from a service, which later will get its data from a web service. But for now we are just going to hard code some data to make things simple.

Adding Autofac

From the applications shared PCL project (Silkweb.Mobile.MountainForecast) choose Add Packages from the Packages folder, search for AutoFac and then add the package to the project.

0

Autofac supports defining your DI configuration in Module classes which keeps the registration of objects nicely encapsulated. More on this here.

Create a class called MountainForecastModule in the root of the project that inherits from Autofac.Module and overrides the Load method.

using System;
using Autofac;
 
namespace Silkweb.Mobile.MountainForecast
{
    public class MountainForecastModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
        }
    }
}

This method is where we will place the registration configuration. At the moment we have nothing really to register so let’s focus on getting our main page to display a list of mountain areas.

Adding a Service

Let’s create our model. Create a class in the models folder to represent a location.

public class Location
{
    public int Id { get; set; }
 
    public string Name { get; set; }
}

Create a Services Folder and add the following interface and implementation for our MountainWeatherService, which contains one simple method to return a list of Mountain Areas.

    public interface IMountainWeatherService
    {
        IEnumerable<Location> GetAreas();
    }

    public class MountainWeatherService : IMountainWeatherService
    {
        public IEnumerable<Location> GetAreas()
        {
            return new Location[]
            {
                new Location { Id = 100, Name = "Area 1" },
                new Location { Id = 101, Name = "Area 2" },
                new Location { Id = 102, Name = "Area 3" },
                new Location { Id = 103, Name = "Area 4" },
                new Location { Id = 104, Name = "Area 5" },
            };
        }
    }

Let’s create a View Model to represent this page. In the ViewModels folder add the following View Models.

public class MountainAreaViewModel
{
    private IMountainWeatherService _mountainWeatherService;
 
    public MountainAreaViewModel(Location location, 
        IMountainWeatherService mountainWeatherService)
    {
        _mountainWeatherService = mountainWeatherService;
        Name = location.Name;
    }
 
    public string Name { get; set; }
}
 
public class MountainAreasViewModel
{
    private readonly IMountainWeatherService _mountainWeatherService;
    private readonly Func<Location, MountainAreaViewModel> _areaViewModelFactory;
 
    public MountainAreasViewModel(IMountainWeatherService mountainWeatherService, 
        Func<Location, MountainAreaViewModel> areaViewModelFactory)
    {
        _areaViewModelFactory = areaViewModelFactory;
        _mountainWeatherService = mountainWeatherService;
        Title = "Mountain Areas";
        GetAreas();
    }
 
    public string Title { get; set; }
 
    public IEnumerable<MountainAreaViewModel> Areas { get; set; }
 
    private void GetAreas()
    {
        var areas = _mountainWeatherService.GetAreas();
        Areas = areas.Select(location => _areaViewModelFactory(location))
            .ToList();
    }
}

MountainAreaViewModel represents a single Mountain Area and currently just exposes it’s Name. MountainAreasViewModel represents the list of areas and exposes these through the Areas property. Notice that both constructors expect an instance of IMountainWeatherService.

The MountainAreasViewModel uses this to get the list of mountain areas. MountainAreaViewModel currently doesn’t use the service but it will do later and I want to show you how we can pass this to both view models using dependency injection. Also notice that MountainAreasViewModel has a second parameter defined as:

Func<Location, MountainAreaViewModel> areaViewModelFactory

Now let’s create the actual view. In the Views folder create a new Forms ContainPage called MountainAreasView.xaml and add the following xaml.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="Silkweb.Mobile.MountainForecast.Views.MountainAreasView"
    Title="{Binding Title}">

    <ListView ItemsSource="{Binding Areas}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Name}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

Here we are simply showing a ListView that is bound to the Areas property with a DataTemplate that displays the Name property for each mountain area. I have also bound the Title of the page to the Title property on the view model.

In the code behind of the view add the following to the constructor.

public MountainAreasView (MountainAreasViewModel viewModel)
{
    InitializeComponent ();
 
    BindingContext = viewModel;
}

This enforces that the view expects a MountainAreasViewModel as a constructor parameter which it then uses to set as its BindingContext.

Now let’s hook all this together with Autofac. Return to the MountainForecastModule we created earlier and add this following registration code.

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterType<MountainWeatherService>()
        .As<IMountainWeatherService>()
        .SingleInstance();
 
    builder.RegisterType<MountainAreaViewModel>();
 
    builder.RegisterType<MountainAreasViewModel>()
        .SingleInstance();
 
    builder.RegisterType<MountainAreasView>()
        .SingleInstance();
}

Notice here we are registering the service against its interface and specifying it as a single instance. We have also registered the the view and view model types. Both MountainAreasViewModel and MountainAreasView are registered as singleton instances because we only need one instance. We will however require multiple instances of MountainAreaViewModel.

Finally in the MountianForecastApp class update the constructor to create the Autofac container and set the MainPage like this.

public MountainForecastApp()
{
    InitializeComponent();
 
    var builder = new ContainerBuilder();
    builder.RegisterModule<MountainForecastModule>();
    var container = builder.Build();
 
    var page = container.Resolve<MountainAreasView>();
    MainPage = new NavigationPage(page);
}

Notice here that we are registering the MountainForecastModule with the ContainerBuilder and then calling build to build and return our container. We then use the container to resolve the MountainAreasView and set the MainPage to a NavigationPage with it’s root set to the view. Also delete MainPage.xaml and MainPageViewModel as we no longer need these.

Now build and run the App in the iOS simulator.

1

Everything works!

MountainWeatherService gets injected into both ViewModels. The MountainAreasViewModel gets injected with the factory function for creating its area items and the AreaViewModel get’s injected with the Location instance it needs to display.

You may be thinking that all this seems a little overly complex just to show this page and pass a couple of parameters to a constructor. This may be true right now, but as I build out this App things will get a bit more complex. What I have set up here will make everything much simpler and easier to extend.

There are a couple of things that I’m not happy about though.

I don’t really like how I’m bootstrapping the Autofac container within the App class. I would prefer to have a separate Bootsrapper class for this task. Let’s fix that. Delete the code in the MountainForecastApp constructor and create a class called Bootstrapper with the following code.

public class Bootstrapper
{
    public static void Run()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<MountainForecastModule>();
        var container = builder.Build();
 
        var page = container.Resolve<MountainAreasView>();
        MountainForecastApp.Current.MainPage = new NavigationPage(page);
    }
}

Update the MountainForecastApp constructor to run the Bootstrapper.

public MountainForecastApp()
{
    InitializeComponent();
    Bootstrapper.Run();
}

This keeps the App class nice and clean and delegates the bootstrapping to the Bootstrapper class. This will yield greater benefits as I build out my App.

I also don’t really like how I’m wiring up my View and View Model by passing in an instance of the View Model to the View. There are better ways to accomplish this, which I will be addressing in my next post.

For now I hope you enjoyed this post and found it useful.

19 thoughts on “Creating a Xamarin Forms App Part 5 : Dependency Injection

  1. Hello again Jonathan, continued thanks for these great articles!

    I’m new to Autofac and was reviewing their “getting started” documentation at http://autofac.readthedocs.org/en/latest/getting-started/index.html. I noticed in their examples that they’re storing a class-level reference to the builder in their app class, whereas you just assign it to a temporary var. They are also wrapping things with using statements to limit the scope of injected class instances and automatically call the needed Dispose() methods. I don’t see similar stuff in your implementation, so I had a couple of questions.

    1. Is their documentation example that shows a class level property for the container outdated? Is that no longer needed to keep the container from being GC’d during the app’s lifecycle?

    2. How about the scope limiting and using statements? Or for that matter implementing Dispose methods? I ask because I had huge problems with memory leaks in my first Xamarin iOS and Android projects. These issues pushed those project deliveries back by 6 weeks. I had to add a lot of using statements and also explicitly insure that Dispose methods were called to get everything to clean up properly. Have you verified with a profiler that your current implementation is being GC’d as expected when things are no longer needed?

    Thanks again. Your blog has been a great source of information for me.

    Like

    1. Hi,

      This is a very good point you have raised. To be honest I tried to keep things as simple as possible in my posts so avoided getting to deep into Autofac and lifetime scope, but it is an important thing to consider. I’ve not really had time to look into it for Xamarin Forms really but I think the same Unit of work principals still apply, perhaps even more so for mobile apps.
      I think the class level property on container in their example is just for convenience to access the container, but it is strongly recommended that you don’t actually do this. Not really sure why they show that example and then recommend against it.
      I think the using statement approach is actually very limiting in that for most scenarios you are going to have some form of Unit of work where you’re resolved instance is going to live and perform some UI functionality which can’t be nested inside a using statement. I think this can be achieved using Resolve<Owned> which will return the lifetime scope and the resolved instance. You can then call dispose on the lifetime scope when the view model is closed. I guess it depends however how you want to manage lifetime scope in your app. Is is always right to dispose of instances when your done? Perhaps there was some overhead in creating them and you may want to keep it’s state so that if you navigate back to the same place your instance is already created. It really does depend on the nature of your app and how you want to manage the lifetime of parts of the UI.

      I think the ViewFactory could easily be modified to provide overrides to resolve scoped views/view models, and Func can be changed to Func<Owned> if you want to create newly scoped instances.

      The best article I’ve seen on this subject is the one provided in the actual autofac documentation by Nicholas Blumhardt.
      http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/

      Let me know how you get on. I may do a post on this if I manage to find the time.

      Like

      1. Thanks for the link to Nicholas’ article on lifetime management! Agreed, it is a great explanation of the scope stuff.

        As far as keeping up with a view’s state, you have to support persisting and restoration of it if you want to consistently offer that ability. Mobile OS’s may terminate your app at any time, so keeping an object in memory isn’t enough. You probably already know that and I understand you were just providing example cases for keeping them around, but I wanted that to be clear for anyone new to mobile development who is reading along.

        Creation overhead is also a totally legit thing to consider too, but I think keeping them around should be discouraged, therefore not the default behavior.

        This is a very important issue to solve imho. If it can be automatically handled at a core level, all the better.

        A little background that you’re free to pass on 🙂 : Back in August 2013, I thought my first Xamarin.iOS app was ready to submit to the App Store. At the last minute, I ran it through the XCode Instruments profiler. My memory consumption was constantly going up as I worked my way through the app! Nothing was being released.

        The memory leaks in Instruments showed thousands of malloc calls requesting very small (16 to 64 bytes on average) chunks of memory. The allocations were Xamarin’s translation layer creating the managed .net class instances to pair with the underlying OS objects. As far as Instruments was concerned, Xamarin was a black box.

        I needed the Xamarin iOS profiler to clearly see where the leaks were occurring. My Xamarin Indie license didn’t include it. Getting it required a $750 upgrade to the Business license. I was not a happy camper!

        I had modeled my app design after the “real world” company directory and field service examples Xamarin had provided at the time. In hindsight, those examples didn’t have anything in place to insure proper memory management. Xamarin’s documentation (online or Evolve 2013 training) didn’t cover it either. There were a few lengthy, heated discussions in their forums regarding these problems at the time, but I don’t know if they’re still around.

        I don’t want to repeat my previous mistakes. I will definitely try to solve this sooner rather than later. I will get back to you with whatever I come up with for sure.

        Like

      2. That is very interesting. It rages me that you had to pay for the upgrade just to sort it out. Xamarin really need to change their whole pricing structure cos it really sucks.
        Memory management is clearly a top priority, even more so for mobile applications. I’d be very interested in hearing how you progress with this. I will be taking a look into it myself and try to get better lifetime scope management in my current app, when I get the time (that old chestnut!).

        Liked by 1 person

      3. Hi Jonathan,

        First of all I would like to thank you for your posts, very helpful!

        I’ve implemented DI using your blog as a baseline. I was just wondering if you had made any progress in regards to managing scopes with autofac in your view factory (and Funcs)? I’m experiencing some memory leaks and it seems as if Autofac might be the culprit… If I discover something interesting I will follow up here.

        Best Regards,
        Dustin

        Like

  2. Hi Jonathan, great article, i have one question how “private readonly Func _areaViewModelFactory;” does the “mapping” between the model Location and the ViewModel ??

    Like

  3. Hi Jonathan!

    Really great series of articles! We started developing Xamarin.Forms for Android and iOS,
    but your blog gives me a lot of new ideas to better/ cleaner separate our code.

    I tried to open the SourceCode link at the end of this post, but it took me nowhere –
    or better to OneDrive stating “This item might not exist or is no longer available”.

    Is it only shared for specific people or can I access the code somewhere else?

    Thanks a lot for your efforts!

    Gerhard

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s