.NET MAUI Using DependencyService and IPlatformService Step by step Implementation and Top 10 Questions and Answers
 Last Update: April 01, 2025      18 mins read      Difficulty-Level: beginner

.NET MAUI Using DependencyService and IPlatformService

Introduction

.NET Multi-platform App UI (MAUI) is a powerful framework offered by Microsoft, designed to allow developers to create native user interfaces for multiple platforms (iOS, Android, Windows, macOS) from a single codebase. It leverages C# and XAML, making it a familiar choice for .NET developers. One of the key features of .NET MAUI is its ability to interact with platform-specific functionalities through DependencyService and IPlatformService interfaces. This allows developers to seamlessly integrate platform-specific features into their cross-platform applications.

What are DependencyService and IPlatformService?

  1. DependencyService: This is a built-in .NET MAUI service that facilitates communication between shared code and platform-specific implementations. Essentially, it acts as a mediator that allows your shared code to invoke platform-specific code. This is particularly useful when you need to access hardware capabilities (like camera, GPS, etc.), use platform-specific APIs, or perform operations that are not supported in a cross-platform manner.

  2. IPlatformService: Introduced in .NET MAUI, this interface is designed to encapsulate platform-specific services. It provides a standardized way to implement and access platform-specific features, promoting better organization and maintainability of your codebase.

Why Use DependencyService and IPlatformService?

  • Access to Platform-Specific Features: Not all functionalities are available or implemented identically across all platforms. For example, camera access, GPS location services, or even specific UI elements may behave differently. DependencyService and IPlatformService enable developers to access and use these unique features effectively.

  • Code Reusability: By using DependencyService and IPlatformService, developers can write platform-independent code that delegates platform-specific tasks to the respective platform implementations. This reduces duplication of code and enhances maintainability.

  • Decoupling: These services promote a decoupled architecture, where shared code does not need to be tightly coupled with platform-specific code. This separation of concerns simplifies development and testing.

  • Scalability: As your application grows and supports more platforms, using DependencyService and IPlatformService makes it easier to add and manage new platform-specific implementations.

How to Implement DependencyService and IPlatformService in .NET MAUI

Implementing DependencyService

  1. Define an Interface in Shared Code: Start by defining an interface in your shared project that outlines the methods you need to invoke on platform-specific code.

    public interface ICameraService
    {
        string CapturePhoto();
    }
    
  2. Implement the Interface for Each Platform: Create platform-specific implementations of the interface in each target platform project.

    • Android:

      [assembly: Dependency(typeof(CameraServiceAndroid))]
      namespace MyApp.Droid
      {
          public class CameraServiceAndroid : ICameraService
          {
              public string CapturePhoto()
              {
                  // Platform-specific code to capture photo on Android
                  return "Photo captured on Android";
              }
          }
      }
      
    • iOS:

      [assembly: Dependency(typeof(CameraServiceiOS))]
      namespace MyApp.iOS
      {
          public class CameraServiceiOS : ICameraService
          {
              public string CapturePhoto()
              {
                  // Platform-specific code to capture photo on iOS
                  return "Photo captured on iOS";
              }
          }
      }
      
  3. Invoke Platform-Specific Code from Shared Code: Use DependencyService to resolve the platform-specific implementation and invoke the methods.

    public class MainPageViewModel : BaseViewModel
    {
        public ICommand CapturePhotoCommand { get; }
    
        public MainPageViewModel()
        {
            CapturePhotoCommand = new Command(() =>
            {
                var cameraService = DependencyService.Get<ICameraService>();
                var photoPath = cameraService.CapturePhoto();
                Debug.WriteLine(photoPath);
            });
        }
    }
    

Implementing IPlatformService

  1. Define an Interface in Shared Code: Similar to DependencyService, define an interface in your shared project.

    public interface IFilePickerService
    {
        Task<string> PickFileAsync();
    }
    
  2. Implement the Interface for Each Platform: Create platform-specific implementations of the interface in each target platform project.

    • Android:

      [assembly: MauiService(typeof(FilePickerServiceAndroid))]
      namespace MyApp.Droid
      {
          public class FilePickerServiceAndroid : IFilePickerService
          {
              public async Task<string> PickFileAsync()
              {
                  // Platform-specific code to pick file on Android
                  return "File picked on Android";
              }
          }
      }
      
    • iOS:

      [assembly: MauiService(typeof(FilePickerServiceiOS))]
      namespace MyApp.iOS
      {
          public class FilePickerServiceiOS : IFilePickerService
          {
              public async Task<string> PickFileAsync()
              {
                  // Platform-specific code to pick file on iOS
                  return "File picked on iOS";
              }
          }
      }
      
  3. Register the Platform Service with the DI Container: Register the platform-specific implementation in the MauiProgram.cs file.

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });
    
            builder.Services.AddSingleton<IFilePickerService, FilePickerService>();
    
            return builder.Build();
        }
    }
    
  4. Invoke Platform-Specific Code from Shared Code: Use constructor dependency injection to resolve and invoke the platform-specific implementation.

    public class FilePickerViewModel : BaseViewModel
    {
        private readonly IFilePickerService _filePickerService;
    
        public ICommand PickFileCommand { get; }
    
        public FilePickerViewModel(IFilePickerService filePickerService)
        {
            _filePickerService = filePickerService;
            PickFileCommand = new Command(async () =>
            {
                var filePath = await _filePickerService.PickFileAsync();
                Debug.WriteLine(filePath);
            });
        }
    }
    

Best Practices

  • Consistent Interface Design: Ensure the interfaces defined in shared code are consistent across all platforms. This helps in maintaining a clean and maintainable codebase.

  • Error Handling: Always include error handling logic in your platform-specific implementations to manage exceptions and edge cases.

  • Unit Testing: Write unit tests for your shared code and use mocking frameworks to simulate platform-specific implementations. This ensures your code is robust and functions as expected.

  • Documentation: Document your interfaces and platform-specific implementations thoroughly. This is especially important when working in teams to ensure everyone understands the purpose and usage of each service.

Conclusion

DependencyService and IPlatformService are essential tools in the .NET MAUI toolkit, allowing developers to seamlessly integrate platform-specific features into their cross-platform applications. By following best practices and understanding how to implement and use these services effectively, developers can create powerful, robust, and maintainable applications that leverage the unique capabilities of each platform.

.NET MAUI Using DependencyService and IPlatformService: A Step-by-Step Guide

.NET Multi-platform App UI (.NET MAUI) is a powerful framework for building native mobile and desktop applications with a single codebase. One of the key features of .NET MAUI is its ability to interact with platform-specific APIs through the use of DependencyService and IPlatformService. In this guide, we will explore how to set up a route, run the application, and understand the data flow when using these services, providing a step-by-step approach suitable for beginners.

Prerequisites

Before diving into the specifics, ensure you have the following:

  • Visual Studio: Install the latest version of Visual Studio with .NET MAUI workload.
  • Basic Knowledge of .NET and C#: Understanding of basic C# programming and .NET concepts.
  • Understanding of .NET MAUI Basics: Familiarity with creating and running .NET MAUI applications.

Setting Up the .NET MAUI Project

  1. Create a New Project:

    • Open Visual Studio.
    • Navigate to File > New > Project.
    • In the Create a new project dialog, search for ".NET MAUI App" and select it.
    • Click Next.
    • Enter your project name, choose a location, and click Create.
    • Choose a .NET MAUI App template, configure the target platforms, and click Create.
  2. Set Up Routing:

    • In your App.xaml.cs, set up a route for your pages. Replace the existing MainPage initialization with:
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            Routing.RegisterRoute(nameof(MainPage), typeof(MainPage));
            Routing.RegisterRoute(nameof(PlatformServicePage), typeof(PlatformServicePage));
            MainPage = new AppShell();
        }
    }
    
    • Create a new ContentPage called PlatformServicePage.xaml and register its route in the App.xaml.cs file.
  3. Define the Platform-Specific Interface:

    • Create an interface for the platform-specific service in the shared library. For example, let’s create a simple interface ITimeService to get the current time from the device.
    public interface ITimeService
    {
        string GetCurrentTime();
    }
    
    • Implement this interface in each platform’s project.
      • iOS: Create TimeServiceiOS.cs in the iOS project:

        using Foundation;
        using MyApp;
        
        [assembly: Xamarin.Forms.Dependency(typeof(TimeServiceiOS))]
        namespace MyApp.iOS
        {
             public class TimeServiceiOS : ITimeService
             {
                 public string GetCurrentTime()
                 {
                     NSDate now = NSDate.Now;
                     DateTime dateTime = (DateTime)now;
                     return dateTime.ToString("HH:mm:ss");
                 }
             }
        }
        
      • Android: Create TimeServiceAndroid.cs in the Android project:

        using Android.Util;
        using MyApp;
        
        [assembly: Xamarin.Forms.Dependency(typeof(TimeServiceAndroid))]
        namespace MyApp.Android
        {
             public class TimeServiceAndroid : ITimeService
             {
                 public string GetCurrentTime()
                 {
                     Log.Debug("TimeServiceAndroid", "Getting Current Time");
                     return DateTime.Now.ToString("HH:mm:ss");
                 }
             }
        }
        
  4. Using DependencyService in the Shared Code:

    • In your PlatformServicePage.xaml.cs, use DependencyService to get the current time from the platform-specific service.
    using Xamarin.Forms;
    
    public partial class PlatformServicePage : ContentPage
    {
        public PlatformServicePage()
        {
            InitializeComponent();
            ShowCurrentTime();
        }
    
        private void ShowCurrentTime()
        {
            ITimeService timeService = DependencyService.Get<ITimeService>();
            string currentTime = timeService.GetCurrentTime();
            TimeLabel.Text = $"Current Time: {currentTime}";
        }
    }
    
  5. Designing the UI in PlatformServicePage.xaml:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MyApp.PlatformServicePage"
                 Title="Platform Service Page">
        <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
            <Label x:Name="TimeLabel" FontSize="Title" Text="Current Time: " />
        </StackLayout>
    </ContentPage>
    
  6. Navigating to PlatformServicePage:

    In your MainPage.xaml, add a button to navigate to PlatformServicePage.

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MyApp.MainPage"
                 Title="Main Page">
        <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
            <Button Text="Show Time" Clicked="OnShowTimeButtonClicked" />
        </StackLayout>
    </ContentPage>
    
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    
        private async void OnShowTimeButtonClicked(object sender, EventArgs e)
        {
            await Shell.Current.GoToAsync(nameof(PlatformServicePage));
        }
    }
    

Running the Application

  1. Build and Run the Application:

    • Select your target platform (iOS, Android, Windows, or macOS) in Visual Studio.
    • Click Run (F5) or Start Debugging to build and run the application.
  2. Interact with the Application:

    • Upon launching, you should see the main page with a "Show Time" button.
    • Tap the "Show Time" button to navigate to PlatformServicePage.
    • The label Current Time will be updated with the current time fetched from the platform-specific service.

Understanding the Data Flow

  1. Initialization:

    • When the application starts, the App constructor is called where routing is set up and the MainPage is initialized.
  2. Navigation:

    • Upon pressing the "Show Time" button, the OnShowTimeButtonClicked method is triggered.
    • Shell.Current.GoToAsync(nameof(PlatformServicePage)) navigates to PlatformServicePage using the registered route.
  3. DependencyService Interaction:

    • In the PlatformServicePage constructor, the ShowCurrentTime method is called.
    • DependencyService.Get<ITimeService>() resolves the platform-specific implementation of ITimeService.
    • For iOS, TimeServiceiOS is used, and for Android, TimeServiceAndroid is used.
    • The GetCurrentTime method of the resolved service is called, and the result is displayed in a label.

Conclusion

By following this step-by-step guide, you have learned how to set up routing, navigate between pages, and use DependencyService and IPlatformService in a .NET MAUI application. Understanding these concepts will enable you to create rich, platform-specific experiences while maintaining a unified codebase, making it easier to manage and scale your applications.

Feel free to experiment with different platform-specific services and explore more advanced features of .NET MAUI to further enhance your skills as a mobile and desktop application developer.

Top 10 Questions and Answers: .NET MAUI Using DependencyService and IPlatformService

1. What is .NET MAUI, and why is it important for mobile app development?

Answer: .NET Multi-platform App UI (MAUI) is a cross-platform framework that enables developers to build applications for multiple operating systems such as iOS, Android, macOS, Windows, and Linux using a single codebase. It leverages the .NET ecosystem, offering a powerful set of tools and libraries that are widely used in enterprise software development. MAUI replaces Xamarin.Forms as the official Microsoft framework for building cross-platform apps, providing a more modern and efficient development experience.

2. What is DependencyService in .NET MAUI, and how is it used?

Answer: DependencyService in .NET MAUI is a service locator used to resolve platform-specific implementations of an interface. It allows you to access native features on each platform without writing platform-specific code in your shared project. Here's how it works:

  • Define an interface in the shared project that represents the functionality you want.
  • Implement the interface for each platform in the respective platform projects.
  • Use DependencyService to resolve the platform-specific implementation from the shared code.

Example:

// Shared Project
public interface IMyDependency
{
    string GetData();
}

// Android Project
public class MyDependency : IMyDependency
{
    public string GetData()
    {
        return "Android Data";
    }
}

// iOS Project
public class MyDependency : IMyDependency
{
    public string GetData()
    {
        return "iOS Data";
    }
}

// Usage in Shared Project
var data = DependencyService.Get<IMyDependency>().GetData();

3. Can you explain the role of IPlatformService in .NET MAUI?

Answer: IPlatformService is not an official interface provided by .NET MAUI. It seems like a possible custom or hypothetical name for an interface you might define to encapsulate platform-specific services. In .NET MAUI, you typically use DependencyService to access platform-specific implementations through custom interfaces. If you intended to refer to a specific platform service, providing more context could help clarify the usage.

For example, if IPlatformService is a custom interface you define, you would:

  1. Define the IPlatformService interface in your shared code.
  2. Implement the interface for each platform in the respective platform projects.
  3. Use DependencyService to resolve the platform-specific implementation.

4. How can I handle platform-specific permissions in a .NET MAUI app?

Answer: Handling platform-specific permissions involves requesting and checking permissions before using certain features that require user consent. In .NET MAUI, you can use platform-specific APIs or packages to manage permissions. For example, you can use Xamarin.Essentials, which provides a consistent API for requesting permissions.

Here's a basic example using Xamarin.Essentials for accessing the camera:

using Xamarin.Essentials;

async Task CheckCameraPermission()
{
    var status = await Permissions.RequestAsync<Permissions.Camera>();

    if (status == PermissionStatus.Granted)
    {
        // Camera permission granted
    }
    else
    {
        // Camera permission denied
    }
}

5. What are the best practices for using DependencyService in .NET MAUI applications?

Answer: Best practices for using DependencyService in .NET MAUI include:

  • Interface First: Define clear interfaces for the functionality you need to access on each platform.
  • Shared Code: Keep your shared code clean and free of platform-specific logic.
  • Null Checks: Always check the result of DependencyService.Get<T>() for null to avoid runtime exceptions.
  • Error Handling: Implement error handling to manage scenarios where platform-specific services are unavailable.
  • Testing: Write unit tests for your shared code and integration tests for platform-specific implementations.

6. How can I access platform-specific APIs in .NET MAUI without DependencyService?

Answer: Accessing platform-specific APIs without DependencyService can be done using partial classes or platform-specific services provided by .NET MAUI or third-party libraries. Here are two common approaches:

  • Partial Classes: Define partial classes in your shared project that implement the platform-specific logic in the respective platform projects.
// Shared Project
public partial class MyPlatformClass
{
    public partial void DoSomething();
}

// Android Project
public partial class MyPlatformClass
{
    public partial void DoSomething()
    {
        // Android-specific logic
    }
}

// iOS Project
public partial class MyPlatformClass
{
    public partial void DoSomething()
    {
        // iOS-specific logic
    }
}
  • Platform-Specific Services: Use built-in services or libraries that provide platform-specific functionality. For example, Xamarin.Essentials offers various platform-specific services.

7. Can I use DependencyService to call platform-specific asynchronous methods?

Answer: Yes, you can use DependencyService to call platform-specific asynchronous methods. The methods in your platform-specific implementations can be asynchronous, and you can use async/await to consume them. Here's an example:

// Shared Project
public interface IMyDependency
{
    Task<string> GetDataAsync();
}

// Android Project
public class MyDependency : IMyDependency
{
    public async Task<string> GetDataAsync()
    {
        // Asynchronous Android logic
        await Task.Delay(1000);
        return "Android Data";
    }
}

// iOS Project
public class MyDependency : IMyDependency
{
    public async Task<string> GetDataAsync()
    {
        // Asynchronous iOS logic
        await Task.Delay(1000);
        return "iOS Data";
    }
}

// Usage in Shared Project
var data = await DependencyService.Get<IMyDependency>().GetDataAsync();

8. What are the limitations of using DependencyService in .NET MAUI?

Answer: While DependencyService is powerful, it has some limitations:

  • Complexity: When dealing with many platform-specific features, maintaining multiple platform-specific implementations can become complex.
  • Testing: Testing platform-specific code can be challenging because it requires running on different devices or emulators.
  • Performance: Overusing DependencyService for frequent calls to platform-specific methods can impact performance.
  • Consistency: Ensuring consistent behavior across platforms can be difficult, especially with different API versions or user settings.

9. How do I use DependencyService to access native UI components in .NET MAUI?

Answer: Accessing native UI components using DependencyService is possible but not the primary use case. It's more common to use partial views or custom renderers for UI components. However, if you need to access a native UI component directly, you can implement it using DependencyService.

Here's an example of accessing a native UI component (e.g., a custom view) using DependencyService:

  1. Define an interface in the shared project.
public interface INativeView
{
    View GetView();
}
  1. Implement the interface in the platform-specific projects.
// Android Project
public class NativeView : INativeView
{
    public View GetView()
    {
        var linearLayout = new LinearLayout(Platform.CurrentActivity)
        {
            Orientation = Orientation.Vertical
        };

        var textView = new TextView(Platform.CurrentActivity);
        textView.Text = "Native Android View";
        linearLayout.AddView(textView);

        return linearLayout;
    }
}

// iOS Project
public class NativeView : INativeView
{
    public View GetView()
    {
        var stackView = new UIStackView
        {
            Axis = UILayoutConstraintAxis.Vertical,
            Alignment = UIStackViewAlignment.Fill,
            Distribution = UIStackViewDistribution.Fill
        };

        var label = new UILabel
        {
            Text = "Native iOS View"
        };
        stackView.AddArrangedSubview(label);

        return stackView.ToView();
    }
}
  1. Use DependencyService to resolve the platform-specific implementation and add it to your layout.
var nativeView = DependencyService.Get<INativeView>().GetView();
this.Content = nativeView;

10. What is the future of DependencyService in .NET MAUI, and how will it evolve?

Answer: The future of DependencyService in .NET MAUI is promising but uncertain. As .NET MAUI continues to evolve, there might be changes to how platform-specific services are accessed. Currently, DependencyService remains a key component for resolving platform-specific implementations, but there could be new alternatives or improvements in upcoming releases.

One potential future direction is the integration of more modern dependency injection patterns and tools that could provide a more robust and flexible way to manage platform-specific services. However, for the foreseeable future, DependencyService will likely remain a standard approach for accessing platform-specific features in .NET MAUI applications.


By understanding and effectively utilizing DependencyService, you can build powerful, cross-platform applications in .NET MAUI that leverage the unique capabilities of each operating system.