Resolving Dependencies In Platform Pages, Renderers, Effects and Elements with Xamarin.Forms and Prism

Resolving Dependencies In Platform Pages, Renderers, Effects and Elements with Xamarin.Forms and Prism

We’ve been using Prism for a number of our Xamarin.Forms projects and for the most part we rely on the services being injected into our view models but a scenario came up recently where we wanted to access one of our services from within the platform implementation of a renderer. We were using DryIoC and needed to come up with a mechanism to resolve dependencies that had been registered with DryIoC via Prism. I recalled seeing in Brian’s What’s New in Prism 7.1 post that support had been added for the Xamarin.Forms Dependency Resolver and was wondering whether we could use that to allow us to resolve dependencies by calling Resolve on the static DependencyService that Xamarin.Forms exposes. In this post I’m going to walk through creating a simple Prism application, register a service and then retrieve it from the code behind of a UWP page (but the same process applies for any renderer, effect, page or element).

To get started with a new Prism application I’m going to make use of the Prism Template Pack that installs as a Visual Studio Extension and includes a variety of project and item templates. In Visual Studio 2019 when you launch the application you can select Create a New Project and be given the option to search for project templates.

image 

Once you’ve selected the Prism Bank App (Xamarin.Forms) you’ll then be prompted to specify the name and location of the project

image

The final step is a Prism specific dialog that allows you to specify which platforms and what IoC container you want to use

image

In this case we’re going with DryIoC but I think the technique will work equally well if you select AutoFac or Unity. After hitting Create Project our solution is setup with four projects: one for each target platform and a project that contains both our view and view models. 

image

My preference is to separate views and viewmodels further but for the timebeing we’ll leave the project structure as it is. The next step is to create and register the service that we want to retrieve from our platform specific code.

public interface IFancyService
{
     string WelcomeText { get; }
}


public class MyFancyService : IFancyService
{
     public string WelcomeText => “Hello Dependency World!”;
}

The MyFancyService needs to be registered with the DI container, which we can do by adding a line to the RegisterTypes method in the App.xaml.cs

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterForNavigation<NavigationPage>();
     containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();


    containerRegistry.Register<IFancyService, MyFancyService>();
}

Let’s switch across to the code behind of the MainPage in the UWP application – note that this page is different from the MainPage that’s in the Xamarin.Forms project which is the page that’s displayed on all platforms. The MainPage in the UWP project is used to host the Xamarin.Forms application when it’s run on Windows. I’m going to add the OnNavigatedTo override method and in it I’m going to attempt to resolve the IFancyService interface using the Xamarin.Forms DependencyService.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
     base.OnNavigatedTo(e);


    var fancy = DependencyService.Resolve<IFancyService>();
}

Running this code we’ll see that the variable fancy is null, meaning that the Resolve method wasn’t able to find any registered implementation of the IFancyService.

image

To fix this, we need to tell Prism to register as a Dependency Resolver, which will mean that the Xamarin.Forms DepedencyService will use the same DI container when resolving instances. This is done by using the overloaded constructor of the PrismApplication class. In the App.xaml.cs of our application, change the call to base to include a second parameter which is set to true.

public App(IPlatformInitializer initializer) : base(initializer, setFormsDependencyResolver: true)
{
}

Running the application now and the fancy variable is set to an instance of the MyFancyService.

image

And there you have it – an easy way to use the Xamarin.Forms DependencyService in conjunction with Prism and DryIoC.

Leave a Reply

Your email address will not be published. Required fields are marked *