Xamarin Forms with Microsoft Dependency Injection

Diego Martin | 07 May 2020

Logo Constant

Xamarin does not use dependency injection out of the box. It has a service locator called DependencyService to register and get services but it does not allow to control the life cycle of the instances and its scope.

Microsoft Dependency Injection

There are some tutorials out there about how to use Autofac and other IoCC with Xamarin.

I recently found a good article on how to add DI with host builder in Xamarin, but it's a bit overkill to add a host just for dependency injection features.

Microsoft has a light DI framework that comes out of the box for DotNet Core applications called Microsoft Dependency Injection.

You don't need to use DotNet Core applications to use it. In fact you can use it in the old .NET framework also.

Obviously with the AspNet Core applications, for example, this DI framework is already built-in and it automatically creates a new scope each time an http request arrives and so on. But as I said, it's possible to use this functionality anywhere, even in .netstandard libraries like Xamarin Forms.

How to add Dependency Injection to a Xamarin Forms application

Add a the Microsoft.Extensions.DependencyInjection nuget dependency to your Xamarin Forms project. Currently the latest version is 3.1,

Create a Startup class where we can do the wiring.

public static class Startup
{
    public static IServiceProvider ServiceProvider { get; set; }

    public static IServiceProvider Init()
    {
        var serviceProvider = 
            new ServiceCollection()
                .BuildServiceProvider();
        ServiceProvider = serviceProvider;

        return serviceProvider;
    }
}

Now there is a service provider in place capable of building the dependency injection container.

We need to test it with a service.

Create an interface to define the contract of a sample service, for example:

public interface IMyService
{
    string GetSomething();
}

and an implementation

public class MyService
    : IMyService
{
    public string GetSomething()
    {
        return "foo";
    }
}

Now create a view model where we will use this service

public class SampleViewModel
{
    private readonly IMyService _myService;

    public SampleViewModel(IMyService myService)
    {
        _myService = myService;
    }

    public void UseIt()
    {
        var id = _myService.GetSomething();
    }
}

And now at any content page, we could resolve the view model where any service gets automatically injected.

public partial class MyPage : ContentPage
{
    public MyPage()
    {
        InitializeComponent();
        BindingContext = Startup.ServiceProvider.GetService<SampleViewModel>();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        ((SampleViewModel)BindingContext).UseIt();
    }
}

We now need to register these services in the dependency injection container.

To make things a bit cleaner, create a new class to have an extension method where we can make all the registrations.

public static class DependencyInjectionContainer
{
    public static IServiceCollection ConfigureServices(this IServiceCollection services)
    {
        services.AddSingleton<IMyService, MyService>();
        services.AddTransient<SampleViewModel>();
        return services;
    }
}

and call this extension method from the Startup

public static class Startup
{
    public static IServiceProvider ServiceProvider { get; set; }

    public static IServiceProvider Init()
    {
        var serviceProvider = 
            new ServiceCollection()
                .ConfigureServices()
                .BuildServiceProvider();
        ServiceProvider = serviceProvider;

        return serviceProvider;
    }
}

The last step is to make sure Init() is executed at the beginning of the application. There are several options, but the most straightforward is to do so at App.xaml.cs inside the constructor that instantiates the application

public App()
{
    InitializeComponent();
    Startup.Init();
    MainPage = new MainPage();
}

The good thing of this dependency injection container is that there are plenty of available extensions to add logging, http client, etc. that you can now easily plug into your application.

For example, if you want to use and HttpClient, simply add the nuGet dependency Microsoft.Extensions.Http and add its registration with either at Startup.cs or DependencyInjectionContainer.cs. For example:

public static class Startup
{
    public static IServiceProvider ServiceProvider { get; set; }

    public static IServiceProvider Init()
    {
        var serviceProvider = 
            new ServiceCollection()
                .AddHttpClient();
                .BuildServiceProvider();
        ServiceProvider = serviceProvider;

        return serviceProvider;
    }
}