Rasmus Tolstrup Christensen

Howto Combine IOC And Xamarin DependencyService

April 07, 2016 | 3 Minute Read

In Xamarin Forms we can use the built-in DependencyService, to use native features. In the terms of dependency injection this approach does work, but it's more of a service locator. If we at the same time use an IOC container like Autofac or just SimpleIoC, this DependencService becomes a bit messy as it by default breaks the constructor injection. Well luckily we can get the best of both by combining the two.

Xamarin Forms DependencyService

In a basic Xamarin Forms application we can use the DependencyService to resolve platform specific/native dependencies if we use a PCL approach. Let’s start by looking how this is done, by resolving a service to resize images implemented in iOS and Android.

/*** PCL project ***/
reasonly _imageResizer;

public class ImageGalleryViewModel()
{
    public ImageGalleryViewModel()
    {
        _imageResizer = DependencyService.Get<IImageResizer> ()
    }
}
/*** iOS project ***/
[assembly: Xamarin.Forms.Dependency (typeof(ImageResizer))]
namespace MyApp.iOS.Services
{
	public class ImageResizer : IImageResizer
	{
        public byte[] Resize (byte[] imageData, float width, float height)
		{
            //....impl omitted
        }
    }
}
/*** Android project ***/
[assembly: Xamarin.Forms.Dependency (typeof(ImageResizer))]
namespace MyApp.Droid.Services
{
	public class ImageResizer : IImageResizer
	{
        public byte[] Resize (byte[] imageData, float width, float height)
		{
            //....impl omitted
        }
    }
}

The important step to note here, is how we get the dependency into the ViewModel. In many MVVM implementations a very common approach is contructor injection. Tthis makes it easy to inject other implementations during testing and most of all it’s very clear to the consumer of the ViewModel, if it requires any dependencies. The use of the DependencyService in the code above, makes it more of a blackbox.

Open the box and inject…

As Xamarin Forms DependencyService is a great service, a more common usage in MVVM implementations, is to use an IoC Container like Autofac or SimpleIOC that’s baked into MVVMLight. These containes makes it possible to do constructor injection, by register all needed dependencies upfront. As we have a ViewModel, we can assume it’s used together with a view as a BindingContext, so the first registration is to register the ViewModel in the container itself. To see how all this can be autowired, read my previous [post].(http://rasmustc.com/blog/Index-ViewModelLocator-With-MvvmLight-And-Xamarin-Forms/)

First we register the ViewModel as it’s a dependency to a view.

public class ViewModelLocator : DynamicObject
{    
    public ViewModelLocator ()
    {
        ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default); 
        SimpleIoc.Default.Register<ImageGalleryViewModel> ();
    }
}

Next we change the signature of the ImageGalleryViewModel to require IImageResizer as a dependency.

public ImageGalleryViewModel (IImageResizer imageResizer)

As the IoC container is responsible of resolving dependencies, we need to ensure our viewmodel can be resolved with the new dependency from the container. Well it’s really simple.

public class ViewModelLocator : DynamicObject
{    
    public ViewModelLocator ()
    {
        ServiceLocator.SetLocatorProvider (() => SimpleIoc.Default);
        var di = SimpleIoc.Default;
        di.Register<IImageResizer> (() => DependencyService.Get<IImageResizer> ()); 
        di.Register<ImageGalleryViewModel> ();
    }
}

All we need to do is move the DependencyService into the container registration. As the code runs on a specific platform, iOS or Android, our ViewModel is resolved. The specific platform implementation of IImageResizer will then be resolved as the dependency required by our ViewModel, and now we have a more clean implementation.

comments powered by Disqus