OneShot 3.1.0
dotnet add package OneShot --version 3.1.0
NuGet\Install-Package OneShot -Version 3.1.0
<PackageReference Include="OneShot" Version="3.1.0" />
<PackageVersion Include="OneShot" Version="3.1.0" />
<PackageReference Include="OneShot" />
paket add OneShot --version 3.1.0
#r "nuget: OneShot, 3.1.0"
#:package OneShot@3.1.0
#addin nuget:?package=OneShot&version=3.1.0
#tool nuget:?package=OneShot&version=3.1.0
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
- Prefer Constructor Injection - Most explicit and testable
- Use Scoped for Request/Frame Lifetime - Ideal for Unity Update loops
- Avoid Disposable Transients - Can cause memory leaks
- Use Labels for Multiple Implementations - Type-safe alternative to string keys
- 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 | Versions 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. |
-
.NETStandard 2.1
- JetBrains.Annotations (>= 2021.3.0)
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 |