Bridging the Gap: Using DependencyService for Platform APIs in Xamarin.Forms
Learn how to use DependencyService in Xamarin.Forms to access native iOS and Android APIs from a shared project using the service locator pattern.
08 Apr 2026, 09:29 UTC

The Shared Code Wall
When building with Xamarin.Forms, you spend most of your time in a shared .NET Standard project. However, you eventually hit a wall: the shared project cannot see native APIs. If you need to check the battery level, access the secure keychain, or trigger a platform-specific haptic vibration, the shared project has no direct way to call those Android or iOS libraries.
The DependencyService is the built-in service locator designed to solve this. It allows you to define a "contract" in your shared code and fulfill that contract separately in each platform project, keeping your business logic clean and platform-agnostic.
Defining the Contract
The process starts with an interface. This interface acts as the bridge; it tells the shared project what functionality is available without needing to know how the platform actually performs the task.
For example, if you need to retrieve the device's unique hardware model, you define an interface in the shared project:
public interface IDeviceHardware
{
string GetDeviceModel();
}
Implementing Platform Logic
Once the interface exists, you must create a class in each platform project (Android and iOS) that implements this interface. The critical step here is the [assembly: Dependency(...)] attribute. This attribute registers the class with the DependencyService at startup, so the shared project can find it later.
Android Implementation
In the Android project, you use the Android SDK to get the model:
[assembly: Xamarin.Forms.Dependency(typeof(YourApp.Droid.AndroidHardware))]
namespace YourApp.Droid
{
public class AndroidHardware : IDeviceHardware
{
public string GetDeviceModel()
{
return Android.OS.Build.Model;
}
}
}
iOS Implementation
In the iOS project, you use UIKit:
[assembly: Xamarin.Forms.Dependency(typeof(YourApp.iOS.IosHardware))]
namespace YourApp.iOS
{
public class IosHardware : IDeviceHardware
{
public string GetDeviceModel()
{
return UIKit.UIDevice.CurrentDevice.Model;
}
}
}
Consuming the Service
To use the service in your shared XAML or C# code, you call DependencyService.Get<T>(). This method looks up the registered implementation for the current platform at runtime.
Example usage in a ViewModel or Page:
var hardwareService = DependencyService.Get<IDeviceHardware>();
if (hardwareService != null)
{
string model = hardwareService.GetDeviceModel();
// Update UI with the model name
}
Trade-offs and Architectural Risks
While DependencyService is convenient, it is a Service Locator pattern, which introduces a few specific challenges:
- Testing Difficulty: Because
DependencyService.Getis a static call, it is harder to mock during unit testing compared to constructor-based Dependency Injection (DI). - Interface Bloat: Creating an interface for every small native feature can lead to a fragmented architecture. Group related platform features into a single service interface where possible.
- Runtime Failures: If you forget to add the
[assembly: Dependency]attribute in one of the platforms,Get<T>()will returnnull, potentially leading to aNullReferenceExceptionif not checked.
Verification and Testing
To verify the implementation, run the application on both an Android emulator and an iOS simulator. Trigger the code path that calls the service and ensure the returned string matches the specific hardware of that emulator. If the app crashes or returns null, check that the [assembly: Dependency] attribute is placed outside the namespace declaration at the top of the platform file.
Moving Toward .NET MAUI
It is important to note that Xamarin.Forms is being superseded by .NET MAUI. While the concept of platform-specific code remains, MAUI shifts toward a more robust Dependency Injection container registered in MauiProgram.cs, replacing the need for the static DependencyService locator.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.