mcpField
M
maui-platform-invoke

maui-platform-invoke

github.com/davidortinauDevelopment17648 installsUpdated 16w ago
Repository

About maui-platform-invoke

maui-platform-invoke is a guidance skill for .NET MAUI developers implementing platform-specific code. It explains when to use partial classes, interfaces, dependency injection, and conditional compilation, with common pitfalls to avoid.

Key features

  1. 01Choosing a platform-code pattern
  2. 02Using partial classes across platforms
  3. 03Separating implementations with interfaces
  4. 04Avoiding conditional compilation pitfalls
  5. 05Handling Android activity nullability

Use cases

  1. 01Structuring platform-specific service logic
  2. 02Making shared code easier to unit test
  3. 03Reviewing platform compilation and fallback issues

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-platform-invoke

After installing, type/maui-platform-invokein Claude Code to confirm it loaded.

Bundled filesreferences/platform-invoke-api.md

Details

From the project README

Platform Invoke — Gotchas & Best Practices

Decision Framework

ScenarioApproach
1–5 lines, one-off check#if ANDROID conditional compilation
Service with logic, testablePartial classes in Platforms/ folders
Swappable implementations, mockingInterface + DI registration
Team prefers *.android.cs namingCustom file patterns in .csproj

Default choice: partial classes + interface + DI. Only use #if for trivial inline checks.

Common Mistakes

1. Overusing #if directives
// ❌ Complex logic buried in #if blocks — untestable, hard to read
public async Task<bool> CheckConnectivity()
{
#if ANDROID
    // 30 lines of Android networking code...
#elif IOS
    // 25 lines of iOS networking code...
#endif
}

// ✅ Use partial classes — each platform file is clean and testable
// Services/ConnectivityService.cs (shared)
public partial class ConnectivityService
{
    public partial Task<bool> CheckConnectivityAsync();
}
// Platforms/Android/Services/ConnectivityService.cs
public partial class ConnectivityService
{
    public partial Task<bool> CheckConnectivityAsync() { /* Android impl */ }
}
2. Mismatched namespaces in partial classes

All partial class files must use the same namespace, or they become separate classes.

// ❌ Different namespaces — creates TWO unrelated classes
// Services/MyService.cs
namespace MyApp.Services;
public partial class MyService { }

// Platforms/Android/MyService.cs
namespace MyApp.Platforms.Android;  // WRONG!
public partial class MyService { }

// ✅ Same namespace everywhere
namespace MyApp.Services;
public partial class MyService { }
3. Depending on concrete classes in shared code
// ❌ Shared code depends on concrete platform type — can't mock in tests
public class MyViewModel
{
    readonly DeviceOrientationService _service = new();
}

// ✅ Depend on interface — enables unit testing and swapping
public class MyViewModel
{
    readonly IDeviceOrientationService _service;
    public MyViewModel(IDeviceOrientationService service) => _service = service;
}
4. Forgetting the #else fallback
// ❌ Fails compilation on unsupported platforms
public string GetDeviceName()
{
#if ANDROID
    return Android.OS.Build.Model;
#elif IOS
    return UIKit.UIDevice.CurrentDevice.Name;
#endif  // No return for Windows or other platforms!
}

// ✅ Always include a fallback
#else
    return "Unknown";
#endif

Platform Pitfalls

⚠️ Android: Platform.CurrentActivity can be null

Platform.CurrentActivity is null before OnCreate completes or when the app is in the background. Always null-check or throw a clear exception.

⚠️ MSBuild auto-includes Platforms/{Platform}/ files

Files under Platforms/Android/ are only compiled for Android — no #if needed. But if you put platform code in a shared folder (e.g., Services/), you must use #if or conditional <Compile> items.

⚠️ Custom file patterns need explicit MSBuild conditions

If using *.android.cs naming, files won't auto-include. Add <Compile> items with platform conditions in your .csproj.

Checklist

  • Partial classes share the same namespace across all files
  • Complex platform code uses partial classes, not #if blocks
  • Shared code depends on interfaces, not concrete implementations
  • Interfaces registered in DI in MauiProgram.cs
  • #if blocks include #else fallback for unsupported platforms
  • Platform.CurrentActivity null-checked before use (Android)
  • Custom file patterns (if used) have MSBuild <Compile> conditions

Comments

Markdown supported