Skip to content

Crumpet-Labs/Buttr.Core

Repository files navigation

Buttr

Engine-agnostic dependency-injection container for .NET. Pure C#, zero runtime dependencies.

Quick start · Getting started · Containers · Aliasing · Analyzers · Benchmarks


About

Buttr is a lightweight dependency-injection framework. The Core library is engine-agnostic — it targets netstandard2.1 and has no dependency on Unity, Godot, or any other engine. Game-engine integrations live in sibling repos that vendor these DLLs and add engine-specific glue on top.

Design priorities, in order:

  1. Zero-allocation on the hot path. Resolved singleton Get<T> is 0 B allocated, measured.
  2. API first. The builder chain is what Buttr was designed around — short, fluent, obvious.
  3. Low barrier to entry. If you've used any DI container, you already know the shape.

Assemblies

Assembly Purpose
Buttr.Core DI container, builders, resolvers, lifetimes, scopes, Application<T>
Buttr.Injection [Inject] marker attribute + InjectionProcessor registry — consumed by engine-side source generators
Buttr.Core.Analyzers Roslyn analyzers + fixers, bundled in the Buttr.Core NuGet at analyzers/dotnet/cs/

Quick start

using Buttr.Core;

// 1. Build a container
var builder = new DIBuilder();
builder.Resolvers.AddSingleton<IAuthService, AuthService>();
builder.Resolvers.AddTransient<RequestHandler>();

var container = builder.Build();

// 2. Resolve
var auth = container.Get<IAuthService>();

// 3. Bulk-resolve every implementation of an interface
builder.Resolvers.AddSingleton<StartupCommand>().As<ICommand>();
builder.Resolvers.AddSingleton<ShutdownCommand>().As<ICommand>();
foreach (var cmd in container.All<ICommand>()) cmd.Run();

container.Dispose();

See Getting Started for a full walk-through, Containers for the DIContainer / ScopeContainer / Application distinction, and Aliasing for .As<>() and All<T>() patterns.

Benchmarks (2026-04-19, .NET 8)

Container Get<T> singleton (resolved) Get<T> transient (3 deps) All<T> (5 matches)
DI 13 ns, 0 B 64 ns, 40 B 49 ns, 0 B
Scope 9 ns, 0 B 64 ns, 40 B 48 ns, 0 B
Application (static) 3 ns, 0 B 58 ns, 40 B 71 ns, 0 B

Transient allocation equals the new instance — TryResolve adds no visible overhead. All<T> uses a struct enumerator so foreach is zero-allocation.

Reproducing and full reports in Docs/Benchmarks/.

Install

.NET (NuGet — preferred for non-Unity projects)

dotnet add package Buttr.Core

Brings in the Buttr.Core assembly plus Buttr.Core.Analyzers shipped at analyzers/dotnet/cs/. Add Buttr.Injection separately if you need the [Inject] marker + InjectionProcessor registry (source generators on the consumer side consume this):

dotnet add package Buttr.Injection

Unity (UPM via git URL)

UPM doesn't speak NuGet, so this repo also ships a small UPM package at package/ that vendors the same Core DLLs. Add to your project's Packages/manifest.json:

"com.crumpetlabs.buttr": "https://github.com/Crumpet-Labs/Buttr.Core.git?path=package"

Pin a specific version with #<tag>, e.g. #1.3.2. The package places Buttr.Core.dll and Buttr.Injection.dll under Runtime/Lib/ with minimal meta files — Unity handles the rest.

For the Unity-specific glue (MonoBehaviour/ScriptableObject wiring, scene walker, [Inject] source generator), install the companion Buttr.Unity package alongside:

"com.crumpetlabs.buttr.unity": "https://github.com/Crumpet-Labs/Buttr.Unity.git?path=Assets/Plugins/Buttr"

Buttr.Unity also vendors the Core DLLs, so use either the Core UPM package or Buttr.Unity — not both, or Unity will complain about duplicate assembly imports.

Other engines (Godot / Stride / …)

Engine-specific bridges live in their own repos and vendor the Core DLLs. Pattern: vendor the DLLs, add an engine-specific source generator (or runtime injector) that wires [Inject]-decorated fields at the engine's appropriate lifecycle hook.

Currently shipping:

  • Buttr.Unity (com.crumpetlabs.buttr.unity) — MonoBehaviour / ScriptableObject wiring, scene walker, [Inject] source generator.

Build & test

dotnet build -c Release
dotnet test

Versioning

Semantic — minor bumps for additive features (aliasing in 1.1, analyzers in 1.2, zero-alloc All<T> in 1.3), majors reserved for binary-breaking changes.

Contributing

See Docs/Contributing.md. Short version: keep comments out of code, discuss architectural changes first, and tests must stay green.

License

MIT — see LICENSE.md.

About

The foundation of Buttr DI

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors