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.
Pingback: Platform Services: Part 2 « random bits and bytes