> For the complete documentation index, see [llms.txt](https://docs.parsue.io/aceland-unity-packages/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.parsue.io/aceland-unity-packages/core-packages/injection.md).

# Injection

Dependency injection for Unity Components and plain C# objects.

[![Open Runtime, Paid Editor Tools](https://img.shields.io/badge/Open%20Runtime,%20Paid%20Editor%20Tools-C24B42)](https://docs.parsue.io/aceland-unity-packages/open-and-paid/open-core-and-paid-editor-tools) ![Burst](https://img.shields.io/badge/Burst-Ready-FF6C37) ![CoreCLR Ready](https://img.shields.io/badge/CoreCLR-Ready-4A5BC2)

[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-db61a2?logo=githubsponsors\&logoColor=white)](https://github.com/sponsors/parsue) [![Discord](https://img.shields.io/badge/Discord-Join-5865F2?logo=discord\&logoColor=white)](https://discord.gg/XsCYGnYzuc) [![Github](https://img.shields.io/badge/github-repo-blue?logo=github)](https://github.com/parsue/com.aceland.injection)

### In One Line

Ask for what you need — the container does the wiring.

### Overview

AceLand Injection is a dependency-injection container built for the modern, no-domain-reload era of Unity (Unity 7 / CoreCLR). It resolves plain C# services and Unity components alike, shares a single process-wide container across every package, and wires most types through a **source-generated, zero-reflection** fast path.

You publish services with installers, annotate consumers with `[Inject]` (or the component attributes `[Self]` / `[Parent]` / `[Child]` / ...), and let scene-level **Injection Scope** components build child containers automatically. Async entry points, object pooling, a Roslyn source generator, project settings, and a build-time validation graph round out the toolkit.

The system ships as **two packages** that share the same `AceLand.Injection` namespace:

* **AceLand Injection** — the full runtime container, Unity integration, source generator and editor tools.
* **AceLand Injection Abstractions** — a tiny, engine-free contracts layer (attributes + interfaces). Reference it from a library to publish an injectable API without pulling in the whole container.

Because they share one namespace, your code never has to care which package a type comes from.

{% hint style="info" %}
**This package follows the Open Core & Paid Editor Tools model.** The runtime container, Source Generator, and Abstractions are **free & open source forever** — your game builds and runs without any license. Only the development-time Editor tools (dependency graph, validation, diagnostics) require a paid **AceLand Injection** license (subscription *or* one-time purchase).

Since **v1.0.1** the licensing layer (`com.aceland.licensing`) is an **optional** dependency, not a hard one — it is **not** installed with the package. The first time you open a paid Editor tool without it, Injection offers a one-click install; your runtime and build are never affected either way.

See [Open Core & Paid Editor Tools](/aceland-unity-packages/open-and-paid/open-core-and-paid-editor-tools.md) for what is free vs. paid, activation, seats, Discord support, and billing.
{% endhint %}

### Package Info

#### AceLand Injection (runtime)

<table data-header-hidden><thead><tr><th width="167.7999267578125"></th><th></th></tr></thead><tbody><tr><td>display name</td><td>AceLand Injection</td></tr><tr><td>package name</td><td>com.aceland.injection</td></tr><tr><td>latest version</td><td>1.0.2</td></tr><tr><td>namespace</td><td>AceLand.Injection</td></tr><tr><td>git repository</td><td><a href="https://github.com/parsue/com.aceland.injection.git">https://github.com/parsue/com.aceland.injection.git</a></td></tr><tr><td>dependencies</td><td>com.aceland.injection.abstractions: 1.0.0<br> · com.aceland.licensing is an optional Editor-only add-on</td></tr></tbody></table>

#### AceLand Injection Abstractions (contracts)

<table data-header-hidden><thead><tr><th width="168.59991455078125"></th><th></th></tr></thead><tbody><tr><td>display name</td><td>AceLand Injection Abstractions</td></tr><tr><td>package name</td><td>com.aceland.injection.abstractions</td></tr><tr><td>latest version</td><td>1.0.0</td></tr><tr><td>namespace</td><td>AceLand.Injection</td></tr><tr><td>git repository</td><td><a href="https://github.com/parsue/com.aceland.injection.abstractions.git">https://github.com/parsue/com.aceland.injection.abstractions.git</a></td></tr><tr><td>dependencies</td><td>none (no engine dependency, ~15 KB)</td></tr></tbody></table>

***

### Why Use It

* **One global container across packages.** Publish a service once with `[AutoInstall]`; resolve it anywhere with `DI.Resolve<T>()` — no manual wiring between packages.
* **Zero-reflection fast path.** A Roslyn incremental source generator emits an injection plan per type at compile time; reflection is only a fallback.
* **Unity-native.** An **Injection Scope** builds a container per scene/prefab, component attributes pull from the hierarchy, and injection completes *before* `Awake`.
* **Async startup, built in.** `IAsyncEntryPoint` runs on the main thread via Unity's loop — no UniTask required.
* **See it before you ship.** A node-based graph window plus scene/prefab build-time validation catch missing dependencies early.
* **Domain-reload-off safe.** Every static resets on `SubsystemRegistration`.

***

### How It Works

The runtime implements the abstractions and wires everything through Unity's initialization phases:

<table><thead><tr><th width="239">Phase</th><th>What happens</th></tr></thead><tbody><tr><td><code>SubsystemRegistration</code></td><td><code>DI</code> / <code>InjectionScope</code> reset their statics (domain-reload-off safety).</td></tr><tr><td><code>AfterAssembliesLoaded</code></td><td><code>DI</code> installs the <code>InjectionBridge</code> provider; <code>ComponentResolver</code> hooks component lookups.</td></tr><tr><td><code>BeforeSceneLoad</code></td><td><code>DI.Bootstrap</code> builds the global container and hooks <code>Application.quitting</code>.</td></tr><tr><td>Scene <code>Awake</code> (order −5000)</td><td>each <strong>Injection Scope</strong> builds its container and injects its target.</td></tr><tr><td><code>Start</code> (order −4000)</td><td><code>EntryPointRunner</code> runs <code>Initialize</code> / <code>RunAsync</code>.</td></tr></tbody></table>

Resolution honours three lifetimes — **Singleton**, **Scoped**, **Transient** — and auto-resolves `Func<T>`, `Lazy<T>`, and collections (`IEnumerable<T>`, arrays). See [Registration & Lifetime](/aceland-unity-packages/core-packages/injection/registration-and-lifetime.md) for the full story.

***

### Quick Start

{% tabs %}
{% tab title="Publish a global service" %}

```csharp
using AceLand.Injection;

// Auto-discovered at startup — no manual registration needed.
[AutoInstall]
public sealed class GameInstaller : IGlobalInstaller
{
    public void Install(IContainerBuilder builder)
    {
        builder.Register<IScoreService, ScoreService>(Lifetime.Singleton);
        builder.AddEntryPoint<GameLoop>();   // also runs as an entry point
    }
}
```

{% endtab %}

{% tab title="Consume it" %}

```csharp
using AceLand.Injection;

// Resolve directly from the global container...
var score = DI.Resolve<IScoreService>();

// ...or let injection fill the members of an existing object.
public class Hud : MonoBehaviour
{
    [Inject] private IScoreService _score;
    void Awake() => DI.Inject(this);
}
```

{% endtab %}

{% tab title="Async entry point" %}

```csharp
using System.Threading;
using System.Threading.Tasks;
using AceLand.Injection;

public sealed class GameLoop : IAsyncEntryPoint, ITickable
{
    [Inject] private readonly IScoreService _score;

    public async Task RunAsync(CancellationToken token)
    {
        await Task.Delay(500, token);   // resumes on the main thread
    }

    public void Tick() { /* per-frame */ }
}
```

{% endtab %}
{% endtabs %}

***

### Documentation Map

<table data-search="false"><thead><tr><th width="204.60003662109375">Page</th><th>What you'll learn</th></tr></thead><tbody><tr><td><a href="/aceland-unity-packages/core-packages/injection/injection-points.md">Injection Points</a></td><td><code>[Inject]</code> on ctor/field/property/method, and the component attributes <code>[Self]</code>/<code>[Parent]</code>/<code>[Child]</code>/<code>[FromScene]</code>/<code>[AddComponent]</code>.</td></tr><tr><td><a href="/aceland-unity-packages/core-packages/injection/registration-and-lifetime.md">Registration &#x26; Lifetime</a></td><td>Installers, every <code>Register*</code> call, lifetimes, ids, factories, and auto-resolved shapes.</td></tr><tr><td><a href="/aceland-unity-packages/core-packages/injection/scopes-and-containers.md">Scopes &#x26; Containers</a></td><td>The global <code>DI</code> container, <code>InjectionScope</code>, child scopes, and inject-before-<code>Awake</code>.</td></tr><tr><td><a href="/aceland-unity-packages/core-packages/injection/entry-points-and-pooling.md">Entry Points &#x26; Pooling</a></td><td><code>IInitializable</code>/<code>ITickable</code>/<code>IAsyncEntryPoint</code> lifecycle callbacks and object/prefab pools.</td></tr><tr><td><a href="/aceland-unity-packages/core-packages/injection/tooling.md">Tooling</a></td><td>The Roslyn <strong>Source Generator</strong> and <strong>Project Settings</strong> (build validation gate).</td></tr><tr><td><a href="/aceland-unity-packages/core-packages/injection/editor-tools.md">Editor Tools</a></td><td>The Injection Graph window, validation window, diagnostics, and menu items.</td></tr><tr><td><a href="/aceland-unity-packages/core-packages/injection/for-package-authors.md">For Package Authors</a></td><td>Depend on the <strong>Abstractions</strong> layer only, and degrade safely via <code>InjectionBridge</code>.</td></tr></tbody></table>

***

### Best Practices

* Keep the runtime dependency in the application/composition layer; reference **abstractions only** from reusable libraries.
* Prefer `[AutoInstall]` global installers over `DI.ConfigureGlobal` for services that should always be present; use `ConfigureGlobal` (before the container builds) for app-specific overrides.
* Use `RegisterIfMissing<...>` in library installers so the host application can override.
* Let an `InjectionScope` inject scene objects rather than calling `DI.Inject` by hand.
* Give competing registrations a stable `Id` and resolve with `[Inject(Id = ...)]`.
* Run the Injection Graph and build-time validation before shipping.

***
