Skip to main content

Xamarin Forms Core components Part 1 Dependency Service

Intro

Xamarin Forms is a collection of controls that can be used and rendered on multiple platforms, and in order of them to function as they are suppose to, they do need a set of core components that defines the way these controls, in how they are created, how they are rendered to how they are used, of course every platform is different and sometimes a platform specific extra configuration is required, specially that there are so many differences between the different platforms in matter of design, user experience and operating system behavior.


So one of the core components of  Xamarin  Forms is the Dependency Service, and by the name suggest it does act as the dependency resolver for all forms controls, if you are not familiar with IOC "Inversion Of Control" and Dependency Injection please refer to the link for a quick intro i wrote a while ago on IOC IOC Part 1 - Inversion of control Principle


And as of such the Dependency Service is the concrete inboxed DI Contatiner for Xamarin Froms, it is not only available under the hood, it still is part of the Xamarin Froms and Xamarin Platform Libraries, and for that you can at will use that dependency service to server whatever you may be able to. 


Just a quick note:- you can wrap the usage of the Xamarin Dependency service inside your own DI container if you are using another DI Container, which is the case most of time.

Which cases you can use Xamarin Dependency Service ?

Coming from the idea that the xamarin forms controls are all using the dependency service, but how ? 
The idea is really simple, Xamarin Forms is a set of Interfaces that are implemeneted differently on each platform it supports, Xamarin forms currently supports Andriod, iOS, MacOS (Beta), Windows Universal Apps, the dependency service resolves the interface to its platform implementation depending on which platform is calling that interface.

So if you need to have any functionality implemented differently on different platform for instance a storage manager that stores photos differently in all platforms, how does this work and what will happen using it?


The Problem?

So as we have said we want to create a storage manager that stores photos on each and every platform but most of our app logic is in the Xamarin.Forms PCL "Portable Class Library", so we will need to wire the Xamarin forms Interface for this to the implementation of the corresponding platform, and here is how :

The Solution

We add the interface that we want to interact with in our app logic "The PCL project", for instance the MVVM ViewModel, and so we start wit the interface

1- The Interface

using System;
public interface IStorageManager
{
   async Task SaveFile(string fileName, byte[] data);
}

As abstract as it is, Just a simple interface that saves a file
now to the implementation part we need to have an implementation for each platform

2-The implementation 

UWP

using System;

public interface StorageManager:IStorageManager
{
    public async Task SaveFile(string fileName, byte[] data)
    {
        try
        {
            FolderPicker folderPicker = new FolderPicker();
            folderPicker.SuggestedStartLocation = PickerLocationId.Desktop;
            folderPicker.FileTypeFilter.Add("*");
            StorageFolder folder = await StorageFolder.GetFolderFromPathAsync();
            file = await folder.CreateFileAsync(fileName);
            File.WriteAllBytes(data);
        }
        catch (System.Exception)
        {
            return false;
        }
        return true;
    }
}



So is it enough for the runtime to know the implementation just because the class inherits from the IStorageManager Interface ??
the answer of course is no, we did not even configure the Dependency Service to resolve this, so here is how we use the dependency service to map the interface to the implementation to be resolved at runtime

Using the the Dependency Attribute



using System;
[assembly: Xamarin.Forms.Dependency (typeof (StorageManager))]
namespace StorageManager.UWP
{
    public interface StorageManager:IStorageManager
    {
        public async Task SaveFile(string fileName, byte[] data)
        {
            try
            {
                FolderPicker folderPicker = new FolderPicker();
                folderPicker.SuggestedStartLocation = PickerLocationId.Desktop;
                folderPicker.FileTypeFilter.Add("*");
                StorageFolder folder = await StorageFolder.GetFolderFromPathAsync();
                file = await folder.CreateFileAsync(fileName);
                File.WriteAllBytes(data);
            }
            catch (System.Exception)
            {
                return false;
            }
            return true;
        }
    }
}

iOS

And for the iOS we can use this implementation :
using System;
[assembly: Xamarin.Forms.Dependency (typeof (StorageManager))]
namespace StorageManager.iOS
{
    public interface StorageManager:IStorageManager
    {
        public async Task SaveFile(string fileName, byte[] data)
        {
            try
            {
                StorageFolder localFolder = ApplicationData.Current.LocalFolder;
                StorageFile sampleFile = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
                await FileIO.WriteAllBytesAsync(sampleFile, text);
            }
            catch (System.Exception)
            {
                return false;
            }
            return true;
        }
    }
}

Android

And for the Android we can use this implementation "Same as iOS":
using System;
[assembly: Xamarin.Forms.Dependency (typeof (StorageManager))]
namespace StorageManager.Android
{
    public interface StorageManager:IStorageManager
    {
        public async Task SaveFile(string fileName, byte[] data)
        {
            try
            {
                StorageFolder localFolder = ApplicationData.Current.LocalFolder;
                StorageFile sampleFile = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
                await FileIO.WriteAllBytesAsync(sampleFile, text);
            }
            catch (System.Exception)
            {
                return false;
            }
            return true;
        }
    }
}

Conclusion: 

The idea to have the dependency service available is to give the power to modify use, and assume the real power behind Xamarin forms, which is writing reusable components that can be used on as much platforms as possible.

Comments

Popular posts from this blog

Xamarin Forms: XAML Creating Custom Controls The MVVM Way

Intro For a growing UI page there always comes a need to create sub views that can be used inside a bigger view, and for that we need custom controls, which are controls that are derived either from a layout or a simple view which is the basic control for almost any UI component in Xamarin forms, and therefore for a start i will use that as an example. And in such example we will create a custom control with a set of bindable properties and explain how they work, also how to add an event that can also be bound to Commands Lets Create the control  I have just went ahead and created a custom control that inherits from Xamarin.Forms.View and have some properties such color and checked all properties to be bound to by the ViewModel serving as the datacontext of the this control. here is the code below using System; using Xamarin.Forms; namespace UserControls { public class CustomView : View { public Color Color { get ; set ;

Windows Phone 8 - Application bar command binding MVVM

This is a short post in which i will explain how on Windows phone 8 to bind the application bar button or menu item, first this is only a fix for the  BindableApplicationbar  which supports windows phone 7 only, i just made it support windows 8 no features added or anything. i have uploaded the dll file here so it can be accessible easily here is the link to download http://sdrv.ms/RApUal now that you got the link lets check how we gonna use it you can refer to BinableApplicationbar  or check out the code here that i actually used in my app and i already read it there !  Add a reference to the BindableApplicationBar library here is the link again  http://sdrv.ms/RApUal Add XML namespace declaration in your page's XAML: xmlns : bar ="clr-namespace:BindableApplicationBar;assembly=BindableApplicationBar" Set Bindable.ApplicationBar property on your page code as in the snippet below: < phone : PhoneApplicationPage >     …     < bar : Bindable.App