Introduction to DependencyService

Understand how DependencyService works to access native platform features

PDF for offline use:
Sample Code:

Let us know how you feel about this.


0/250
Thanks for the feedback!

Overview

DependencyService allows apps to call into platform-specific functionality from shared code. This functionality enables Xamarin.Forms apps to do anything that a native app can do.

DependencyService is a dependency resolver. In practice, an interface is defined and DependencyService finds the correct implementation of that interface from the various platform projects.

How DependencyService Works

Xamarin.Forms apps need three components to use DependencyService:

  • Interface – The required functionality is defined by an interface in shared code.
  • Implementation Per Platform – Classes that implement the interface must be added to each platform project.
  • Registration – Each implementing class must be registered with DependencyService via a metadata attribute. Registration enables DependencyService to find the implementing class and supply it in place of the interface at run time.
  • Call to DependencyService – Shared code needs to explicitly call DependencyService to ask for implementations of the interface.

Note that implementations must be provided for each platform project in your solution. Platform projects without implementations will fail at runtime.

The structure of the application is explained by the following diagram:

Interface

The interface you design will define how you interact with platform-specific functionality. Be careful if you are developing a component to be shared as a component or Nuget package. API design can make or break a package. The example below specifies a simple interface for speaking text that allows for flexibility in specifying the words to be spoken but leaves the implementation to be customized for each platform:

public interface ITextToSpeech {
    void Speak ( string text ); //note that interface members are public by default
}

Implementation per Platform

Once a suitable interface has been designed, that interface must be implemented in the project for each platform that you are targeting. For example, the following classes implement the ITextToSpeech interface on Windows Phone:

namespace TextToSpeech.WinPhone
{
  public class TextToSpeechImplementation : ITextToSpeech
  {
      public TextToSpeechImplementation() {}

      public async void Speak(string text)
      {
          SpeechSynthesizer synth = new SpeechSynthesizer();
          await synth.SpeakTextAsync(text);
      }
  }
}

Note that every implementation must have a default (parameterless) constructor in order for DependencyService to be able to instantiate it. Parameterless constructors cannot be defined by the interface.

Registration

Each implementation of the interface needs to be registered with DependencyService with a metadata attribute. The following code registers the implementation for Windows Phone:

using TextToSpeech.WinPhone;

[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace TextToSpeech.WinPhone {
  ...

Putting it all together, the platform-specific implementation looks like this:

[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace TextToSpeech.WinPhone {
  public class TextToSpeechImplementation : ITextToSpeech
  {
      public TextToSpeechImplementation() {}

      public async void Speak(string text)
      {
          SpeechSynthesizer synth = new SpeechSynthesizer();
          await synth.SpeakTextAsync(text);
      }
  }
}

Note: that the registration is performed at the namespace level, not the class level.

Universal Windows Platform .NET Native Compilation

UWP projects that use the .NET Native compilation option should follow a slightly different configuration when initializing Xamarin.Forms. .NET Native compilation also requires slightly different registration for dependency services.

In the App.xaml.cs file, manually register each dependency service defined in the UWP project using the Register<T> method, as shown below:

Xamarin.Forms.Forms.Init(e, assembliesToInclude);
// register the dependencies in the same
Xamarin.Forms.DependencyService.Register<TextToSpeechImplementation>();

Note: manual registration using Register<T> is only effective in Release builds using .NET Native compilation. If you omit this line, Debug builds will still work, but Release builds will fail to load the dependency service.

Call to DependencyService

Once the project has been set up with a common interface and implementations for each platform, use DependencyService to get the right implementation at runtime:

DependencyService.Get<ITextToSpeech>().Speak("Hello from Xamarin Forms");

DependencyService.Get<T> will find the correct implementation of interface T.

Solution Structure

The sample UsingDependencyService solution is shown below for iOS and Android, with the code changes outlined above highlighted.

iOS and Android solution

ℹ️

Note: You must provide an implementation in every platform project. If no Interface implementation is registered, then the DependencyService will be unable to resolve the Get<T>() method at runtime.

Xamarin Workbook

If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.