# Maui Dependency Injection

> >

- **Type:** Skill
- **Install:** `agentstack add skill-davidortinau-maui-skills-maui-dependency-injection`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [davidortinau](https://agentstack.voostack.com/s/davidortinau)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [davidortinau](https://github.com/davidortinau)
- **Source:** https://github.com/davidortinau/maui-skills/tree/main/plugins/maui-skills/skills/maui-dependency-injection

## Install

```sh
agentstack add skill-davidortinau-maui-skills-maui-dependency-injection
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Dependency Injection in .NET MAUI

## Lifetime Decision Framework

| Question | Answer → Lifetime |
|---|---|
| Does it hold shared state or is expensive to create? | `AddSingleton` |
| Is it stateless, lightweight, or per-request? | `AddTransient` |
| Do you manage `IServiceScope` yourself? | `AddScoped` |

> ⚠️ **Avoid `AddScoped`** in MAUI — there is no built-in scope per page.
> Using it without manually creating `IServiceScope` gives you singleton
> behaviour silently, which is confusing and error-prone.

### Singleton traps

```csharp
// ❌ ViewModel registered as Singleton — stale data across navigations
builder.Services.AddSingleton();

// ✅ ViewModels are Transient — fresh instance each navigation
builder.Services.AddTransient();
```

> Register **Pages and ViewModels as Transient**. Register **services that hold
> shared state as Singleton** (e.g., `IDataService`, `HttpClient` factory).

---

## Gotcha: XAML Resource Parsing vs. DI Timing

XAML resources (`App.xaml` styles, converters) are parsed **during
`InitializeComponent()`** — before the DI container is fully available. If a
resource or converter needs a service, resolve it in `CreateWindow()`, not
in the constructor.

```csharp
// ❌ Resolving services during XAML parse — container may not be ready
public App(IDataService data)
{
    InitializeComponent(); // XAML parses here
    _data = data;          // may fail for types not yet resolved
}

// ✅ Defer service resolution to CreateWindow
public partial class App : Application
{
    private readonly IServiceProvider _services;

    public App(IServiceProvider services)
    {
        _services = services;
        InitializeComponent();
    }

    protected override Window CreateWindow(IActivationState? activationState)
    {
        // Safe — container is fully built
        var mainPage = _services.GetRequiredService();
        return new Window(new AppShell());
    }
}
```

---

## Gotcha: Unregistered Page Silently Skips DI

If a Page is used in Shell XAML (``) but
**not registered** in `builder.Services`, MAUI instantiates it with the
parameterless constructor. Dependencies are silently `null` — no exception.

```csharp
// ❌ Page not registered — constructor injection silently skipped
// builder.Services.AddTransient(); // missing!

// ✅ Always register pages that need injection
builder.Services.AddTransient();
builder.Services.AddTransient();
```

---

## Anti-Pattern: Service Locator Overuse

```csharp
// ❌ Service locator scattered through code — hard to test, hides dependencies
public void DoWork()
{
    var service = this.Handler.MauiContext.Services.GetService();
    service.Load();
}

// ✅ Constructor injection — explicit, testable
public class MyViewModel(IDataService dataService)
{
    public void DoWork() => dataService.Load();
}
```

> Use explicit resolution (`Handler.MauiContext.Services`) only when constructor
> injection is genuinely unavailable (e.g., inside a custom handler or
> platform callback).

---

## Platform-Specific Registration Pitfall

When using `#if` directives for platform services, ensure the **interface**
is always registered — otherwise consumers on untargeted platforms get a
runtime `null`.

```csharp
// ❌ No registration on Windows — GetService returns null
#if ANDROID
builder.Services.AddSingleton();
#elif IOS || MACCATALYST
builder.Services.AddSingleton();
#endif

// ✅ Cover all platforms or provide a no-op fallback
#if ANDROID
builder.Services.AddSingleton();
#elif IOS || MACCATALYST
builder.Services.AddSingleton();
#elif WINDOWS
builder.Services.AddSingleton();
#endif
```

---

## Checklist

- [ ] Every Page and ViewModel that needs injection is registered in `MauiProgram.cs`
- [ ] Pages/ViewModels are `AddTransient`; shared services are `AddSingleton`
- [ ] Constructor injection used everywhere possible; service locator only as last resort
- [ ] Interfaces defined for any service you need to mock in tests
- [ ] Platform-specific `#if` registrations cover all target platforms (or provide fallback)
- [ ] Late-bound services resolved in `CreateWindow()`, not during XAML parse
- [ ] `AddScoped` only used when you manually manage `IServiceScope`

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [davidortinau](https://github.com/davidortinau)
- **Source:** [davidortinau/maui-skills](https://github.com/davidortinau/maui-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-davidortinau-maui-skills-maui-dependency-injection
- Seller: https://agentstack.voostack.com/s/davidortinau
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
