OneShot 3.1.0

dotnet add package OneShot --version 3.1.0
                    
NuGet\Install-Package OneShot -Version 3.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OneShot" Version="3.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OneShot" Version="3.1.0" />
                    
Directory.Packages.props
<PackageReference Include="OneShot" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OneShot --version 3.1.0
                    
#r "nuget: OneShot, 3.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OneShot@3.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OneShot&version=3.1.0
                    
Install as a Cake Addin
#tool nuget:?package=OneShot&version=3.1.0
                    
Install as a Cake Tool

NuGet Version openupm

OneShot Dependency Injection

A lightweight, high-performance, single-file dependency injection container for Unity and .NET.

Features

  • 🎯 Single File - Entire DI container in one file for easy copy-paste distribution
  • High Performance - Expression compilation for fast instance creation (with IL2CPP fallback)
  • 🔒 Thread Safe - All public APIs are thread-safe using concurrent collections
  • 🎮 Unity Integration - Built-in MonoBehaviour components and scene injection
  • 🏗️ Hierarchical Containers - Parent-child relationships with proper disposal chains
  • 🔧 Flexible Registration - Instance, Transient, Singleton, Scoped, and Factory patterns
  • 🏷️ Type-Safe Labels - Support for labeled dependencies with compile-time safety
  • 📦 Generic Support - Full open generic type registration and resolution

Requirements

  • Unity: 2022.3 or higher
  • .NET: .NET Standard 2.1 or higher
  • C#: 10.0 or higher

Basic Concept of DI

Installation

Option 1: Single File (Simplest)

Copy and paste OneShot.cs into your project.

Option 2: Unity Package Manager

Install via OpenUPM:

openupm add com.quabug.one-shot-injection

Option 3: NuGet Package (.NET)

Install via NuGet:

dotnet add package OneShot

Quick Start

using OneShot;

// Create container
var container = new Container();

// Register types
container.Register<DatabaseService>().Singleton().AsInterfaces();
container.Register<UserRepository>().Scoped().AsSelf();
container.RegisterInstance<ILogger>(new ConsoleLogger()).AsSelf();

// Resolve dependencies
var repository = container.Resolve<UserRepository>();

Core Usage

📚 See Test Cases for comprehensive examples

Container Management

// Create root container
var container = new Container();

// Create child container (inherits parent registrations)
var child = container.CreateChildContainer();

// Create scoped container (auto-disposed)
using (var scope = container.BeginScope())
{
    // Scoped registrations live here
}

// Performance Options
container.EnableCircularCheck = false; // Disable circular dependency checking (default: true in DEBUG)
container.PreAllocateArgumentArrayOnRegister = true; // Pre-allocate for performance (default: false)
container.PreventDisposableTransient = true; // Prevent memory leaks (default: false)

Registration Patterns

Lifetimes
// Transient - New instance each time (default)
container.Register<Service>().AsSelf();

// Singleton - Single instance per container hierarchy
container.Register<Service>().Singleton().AsSelf();

// Scoped - Single instance per container scope
container.Register<Service>().Scoped().AsSelf();

// Instance - Register existing instance
container.RegisterInstance<IConfig>(new AppConfig()).AsSelf();
Interface and Base Class Registration
// Register as specific interface
container.Register<Service>().As<IService>();

// Register as all interfaces
container.Register<Service>().AsInterfaces();

// Register as all base classes
container.Register<Service>().AsBases();

// Register as self and interfaces
container.Register<Service>().AsSelf().AsInterfaces();
Advanced Registration
// Factory registration
container.Register<Func<int>>((container, type) => () => 42).AsSelf();

// With specific constructor parameters
container.Register<Service>().With("config", 123).AsSelf();

// Generic type registration
container.RegisterGeneric(typeof(Repository<>), CreateRepository).AsSelf();

Resolution

// Basic resolution
var service = container.Resolve<IService>();

// Generic resolution
var repository = container.Resolve<Repository<User>>();

// Group resolution
var services = container.ResolveGroup<IService>();

// Create instance without registration
var instance = container.Instantiate<MyClass>();

Injection Types

class Service
{
    // Constructor injection (preferred)
    [Inject]
    public Service(IDatabase db, ILogger logger) { }

    // Field injection
    [Inject] private ICache _cache;

    // Property injection
    [Inject] public IConfig Config { get; set; }

    // Method injection
    [Inject]
    public void Initialize(IEventBus eventBus) { }
}

// Manual injection
var service = new Service();
container.InjectAll(service); // Injects fields, properties, and methods

Labels (Named Dependencies)

// Define labels
interface PrimaryDb : ILabel<IDatabase> { }  // Type-specific label
interface SecondaryDb : ILabel<IDatabase> { }
interface Cache<T> : ILabel<T> { }  // Generic label

// Register with labels
container.Register<PostgresDb>().As<IDatabase>(typeof(PrimaryDb));
container.Register<MySqlDb>().As<IDatabase>(typeof(SecondaryDb));
container.Register<CachedRepository>().As<IRepository>(typeof(Cache<>));

// Use labeled dependencies
class Service
{
    public Service(
        [Inject(typeof(PrimaryDb))] IDatabase primary,
        [Inject(typeof(SecondaryDb))] IDatabase secondary,
        [Inject(typeof(Cache<>))] IRepository cached
    ) { }
}

Unity Integration

ContainerComponent

// Attach container to GameObject
var containerComponent = gameObject.AddComponent<ContainerComponent>();
containerComponent.Value = container;

// Auto-disposal on GameObject destruction

Injector Component

// Add Injector to GameObject for automatic injection
var injector = gameObject.AddComponent<Injector>();
injector.InjectionPhase = InjectionPhase.Awake; // or Start, Update, LateUpdate, Manual

// Components on this GameObject will be injected automatically

Scene Injection

// Inject all eligible components in scene
container.InjectScene();

// Prevent injection on specific GameObjects
gameObject.AddComponent<StopInjection>();

Installer Pattern

public class GameInstaller : MonoBehaviour, IInstaller
{
    public void Install(Container container)
    {
        container.Register<PlayerController>().Singleton().AsSelf();
        container.Register<GameManager>().Scoped().AsInterfaces();
        container.Register<AudioSystem>().Singleton().AsBases();
    }
}

Performance Optimization

Configuration Options

// For high-frequency resolution scenarios
container.PreAllocateArgumentArrayOnRegister = true;

// Disable circular dependency checking in production
#if !DEBUG
container.EnableCircularCheck = false;
#endif

// Prevent memory leaks from disposable transients
container.PreventDisposableTransient = true;

IL2CPP Compatibility

OneShot automatically detects IL2CPP and falls back to reflection-based instantiation when expression compilation is unavailable.

// Works seamlessly in both Mono and IL2CPP
container.Register<Service>().Singleton().AsSelf();

Advanced Features

Circular Dependency Detection

// Automatically detected and throws descriptive exception
container.Register<A>().AsSelf(); // A depends on B
container.Register<B>().AsSelf(); // B depends on A
var a = container.Resolve<A>(); // Throws CircularDependencyException

Disposal Management

// IDisposable instances are automatically disposed
using (var scope = container.BeginScope())
{
    var service = scope.Resolve<DisposableService>();
} // service.Dispose() called automatically

// Child containers cascade disposal
container.Dispose(); // Disposes all child containers and registered IDisposables

Best Practices

  1. Prefer Constructor Injection - Most explicit and testable
  2. Use Scoped for Request/Frame Lifetime - Ideal for Unity Update loops
  3. Avoid Disposable Transients - Can cause memory leaks
  4. Use Labels for Multiple Implementations - Type-safe alternative to string keys
  5. Create Child Containers for Isolation - Test scenarios or modular features

Benchmarks

OneShot is optimized for performance. Run benchmarks:

cd .NET/
dotnet run -c Release --project Benchmark

Testing

.NET Tests

cd .NET/
dotnet test --no-build --verbosity normal

Unity Tests

Run via Unity Test Runner in the Unity Editor

Contributing

Contributions welcome! Please ensure:

  • All tests pass on both Mono and IL2CPP
  • No compiler warnings (warnings as errors enabled)
  • Thread safety maintained
  • Single-file philosophy preserved

License

MIT License - See LICENSE file for details

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.1.0 160 9/3/2025
3.0.1 226 8/22/2023
3.0.0 210 8/19/2023
2.8.2 192 8/18/2023
2.7.2 167 8/18/2023
2.6.2 447 10/4/2022
2.6.1 446 10/2/2022
2.6.0 442 10/1/2022
2.5.0 443 9/29/2022
2.4.0 427 9/29/2022
2.3.1 430 9/28/2022
2.3.0 451 9/27/2022
2.2.1 454 9/27/2022
2.2.0 817 8/25/2022
2.1.2 486 7/5/2022
2.1.1 503 7/4/2022
2.1.0 482 7/2/2022
2.0.4 466 6/28/2022
2.0.3 500 3/9/2022
2.0.2 500 3/4/2022
2.0.1 513 3/4/2022
2.0.0 521 2/24/2022