Platform Services: Part 2

Hello from Las Vegas! I am down in Las Vegas for the Autodesk Forge DevCon and Autodesk University. A total of four days of an absolute fire hose of information and learning! I have a few minutes of downtime and I wanted to provide an update on the new direction of consuming platform specific services in your portable project.

In my original post, I showed you how Prism would use the Xamarin Forms built in dependency service to resolve an object if it couldn’t find it in the container that Prism uses. That was the accepted practice for version 6.3 and earlier, but now, in the upcoming 7.0 release, the authors have specified that all object resolution should be done via the Prism container.

Fortunately it is pretty easy.

In Prism, there is an interface that you implement for each of your platforms: IPlatformInitializer where T is your Prism container. I typically use Unity, so my implementation would look something like this:

public class AndroidInitializer : IPlatformInitializer<IUnityContainer>
{
    public void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<IPortableInterface, DroidImplementation>();
        // other registrations
    }
}

Now you just need to pass that implementation into the LoadApplication call in the platform specific app initialization. Continuing with Android, it looks like the following:


[Activity(Label="projectname" ...)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        global::Xamarin.Forms.Forms.Init(this, bundle);
        LoadApplication(new App(new AndroidInitializer()));
    }
}

From there, it goes into your App object that is derived from your selected container specific PrisApplication class. The constructor takes one parameter of IPlatformInitializer which you just move along to the base constructor.


public class App : PrismApplication
{
    public App(IPlatformInitializer initializer = null)
        : base(initializer)
    {
    }

    /// ... rest of your implementation
}

And there you go: all of your registrations controlled directly within Prism for a one stop shop for managing them.

I will add one small caveat to the information above. I wrote most of this from memory while sitting in a hallway at the Sands Convention Center. Prism is going through a number of changes from 6.3 to 7 and I might have mis-spelled a class name. But I think it should stand up fairly well.

Xamarin Forms, Prism and Platform Services

One question that I have had a few times now is how do I integrate platform specific implementations of services into the Prism Framework? It’s not hard, in fact, you don’t have to do anything at all! Let’s take a look at how it works. I am going to focus on the Unity container: it’s my favorite for no other reason than it was the first container I started using and it has always worked well for me across all different .NET projects. The other containers have similar capability.

Recap Abstracting Platform Services

All the platforms have very similar capabilities, especially in the case of Bluetooth, Bluetooth LE, GPS, text-to-speech etc., but each of these capabilities requires a platform specific process of consuming them. I am sure most know that an interface needs to beĀ  created the portable/shared project and then platform specific implementations in each of the platform projects. But here is a quick recap of what it looks like.

Portable/Shared Project

Create your Xamarin Forms project and use nuget to add Prism.Unity.Forms. The latest stable release at the time of writing was 6.3.0. Once you have your project created, you would need to create your interface definition. Everyone loves to use text-to-speech for these kinds of samples, so let’s do that.


public interface ITextToSpeech
{
    void SayIt(string text);
}

For each of the platforms the parts that we are interested in for the sake of the article is pretty much the same. I won’t reproduce the actual speech code here, but if you are interested in how it is done, there is a good sample on the Xamarin developer site.

Platform Projects

Here is what the class looks like for each of the platforms.


///usings up here
[assembly: Dependency(typeof(AndroidTextToSpeech))]
namespace Sample.Droid
{
    public class AndroidTextToSpeech : ITextToSpeech
    {
        public void SayIt(string text)
        {
            /// do implementation here
        }
    }
}

/// usings up here
[assembly: Dependency(typeof(IosTextToSpeech))]
namespace Sample.iOS
{
    public class IosTextToSpeech : ITextToSpeech
    {
        public void SayIt(string text)
        {
            // do implementation here
        }
    }
}
/// usings up here
[assembly: Dependency(typeof(UwpTextToSpeech))]
namespace Sample.Uwp
{
    public class UwpTextToSpeech : ITextToSpeech
    {
        public void SayIt(string text)
        {
            // do implementation here
        }
    }
}

As promised, each of the platform implementations look the same and this is the pattern you would follow even if you weren’t using a framework like Prism. The key is the attribute just above the namespace statement that registers your implementation with the Xamarin Forms dependency service.

Consuming in ViewModel

Normally we would consume the service in the view model using the following pattern:

public class MyViewModel : BindableBase
{
    private ITextToSpeech _speechService = null;

    public MyViewModel()
    {
        _speechService = DependencyService.Get<ITextToSpeech>();
    }
}

The above looks ok, but it does tie your view model to the Xamarin Forms DependencyService. This makes things a little more painful for testing.

What Prism Does For You

What Prism does for you is remove that dependency on the Xamarin Forms dependency service and allow you to pass in the service as a constructor parameter like follows:

public class MyViewModel : BindableBase
{
    private ITextToSpeech _speechService = null;

    public MyViewModel(ITextToSpeech speechService)
    {
        _speechService = speechService;
    }
}

How does Prism do that? It creates a special extension to the Unity container (similar capabilities exist within the other containers) that basically say to the container if the requested interface isn’t registered in the container, look for it in the Xamarin Forms DependencyService. That’s pretty cool! No additional work is required and you right away have a more testable and maintainable solution. If you are interested in seeing what this looks like, you can look at the
DependencyServiceStrategy class and the ConfigureContainer method in the PrismApplication class.