Skip to content

Repository files navigation

Super Simple Dependency Injection (SSDI)

NuGetLicense: MIT

A lightweight, high-performance dependency injection framework for .NET designed for games and console applications. No container build step required — register types at any point during your application's lifecycle.

Full Documentation — Comprehensive guides, API reference, and advanced features.

Features

  • No build step — Register types dynamically at runtime
  • Fast resolution — Optimized for game loops and high-frequency calls
  • Thread-safe — Lock-free resolution path, safe for multi-threaded environments.
  • Scoped lifetime — Per-player, per-request, or per-session instances
  • Unregister support — Hot-swap implementations at runtime
  • Lightweight — Minimal allocations, ideal for games

Quick Start

Basic Registration and Resolution

varcontainer=newDependencyInjectionContainer();container.Configure(c =>{c.Export<MyService>();c.Export<MyRepository>().Lifestyle.Singleton();c.Export<PlayerData>().As<IPlayerData>().Lifestyle.Scoped();});varservice=container.Locate<MyService>();

Eager Compilation

Enable eager compilation for maximum resolution speed at the cost of longer registration time (The Configure method will take longer to complete).

varcontainer=newDependencyInjectionContainer(){EagerCompilation=true};container.Configure(c =>{c.Export<MyService>();c.Export<MyRepository>().Lifestyle.Singleton();c.Export<PlayerData>().As<IPlayerData>().Lifestyle.Scoped();});varservice=container.Locate<MyService>();

Lifestyles

LifestyleDescription
Transient (default)New instance every resolution
SingletonOne instance for app lifetime
ScopedOne instance per scope
container.Configure(c =>{c.Export<GameEngine>().Lifestyle.Singleton();c.Export<Enemy>();// Transient by defaultc.Export<PlayerInventory>().Lifestyle.Scoped();});

Scoped Services

// Create a scope (e.g., per player)usingvarplayerScope=container.CreateScope();varinventory1=playerScope.Locate<IInventory>();varinventory2=playerScope.Locate<IInventory>();// Same instance within scope// All scoped IDisposable services disposed when scope ends

Interface Registration

SSDI requires explicit interface registration:

container.Configure(c =>{c.Export<SqlRepository>().As<IRepository>();// Multiple implementationsc.Export<AuthHandler>().As<IPacketHandler>();c.Export<GameHandler>().As<IPacketHandler>();});// Resolve all implementationsvarhandlers=container.Locate<IEnumerable<IPacketHandler>>();

Constructor Parameters

container.Configure(c =>{// By typec.Export<GameServer>().WithCtorParam<int>(8080);// By namec.Export<GameServer>().WithCtorParam("port",8080);// By positionc.Export<GameServer>().WithCtorParam(0,"MyServer");// Multiple positionalc.Export<GameServer>().WithCtorPositionalParams("MyServer",8080,true);});

Combined Registration and Runtime Parameters

Register some parameters at configuration time, provide others at resolution:

// Register host at configuration timecontainer.Configure(c =>c.Export<GameServer>().WithCtorParam(0,"game.server.com").WithCtorParam(1,443));// Provide remaining parameter at runtimevarserver=container.Locate<GameServer>(DIParameter.Positional(2,true));// useSsl

Unregistered Event

Subscribe to notifications when services are unregistered:

container.Unregistered+=(sender,args)=>{Console.WriteLine($"Unregistered: {args.UnregisteredType.Name}");if(args.WasDisposed)Console.WriteLine(" Instance was disposed");};

Unregistering Services

// Unregister a type (disposes singleton if IDisposable)container.Unregister<OldService>();// Unregister all implementations of an interfacecontainer.UnregisterAll<IPacketHandler>();// Check registrationif(container.IsRegistered<ILogger>()){ ...}

Pre-built Instances

varconfig=LoadConfiguration();container.Configure(c =>{c.ExportInstance(config).As<IConfiguration>();});

Dynamic Registration

Perfect for plugin systems and runtime extensibility:

// Load plugin assemblyvarassembly=Assembly.LoadFrom(pluginPath);container.Configure(c =>{foreach(vartypeinassembly.GetTypes().Where(t =>typeof(IPlugin).IsAssignableFrom(t)&&!t.IsAbstract)){c.Export(type).As<IPlugin>();}});varplugins=container.Locate<IEnumerable<IPlugin>>();

Performance

Benchmarks comparing SSDI against popular DI containers (Windows 11):

Singleton Resolution

Container.NET 8.NET 10Allocated
Grace4.77 ns2.89 ns-
SSDI6.14 ns3.45 ns-
SimpleInj7.96 ns4.79 ns-
DryIoc5.56 ns4.99 ns-
MS.DI6.10 ns5.82 ns-
Autofac100.16 ns74.12 ns808 B

Transient Resolution

Container.NET 8.NET 10Allocated
Grace66.75 ns48.81 ns240 B
SSDI65.05 ns58.42 ns240 B
DryIoc75.99 ns67.45 ns240 B
MS.DI81.43 ns69.00 ns240 B
SimpleInj106.58 ns86.25 ns240 B
Autofac1,445.70 ns1,179.15 ns8,320 B

Combined (Singleton + Transient)

Container.NET 8.NET 10Allocated
Grace8.95 ns7.49 ns56 B
MS.DI11.19 ns9.27 ns56 B
DryIoc10.90 ns9.71 ns56 B
SimpleInj13.27 ns9.85 ns56 B
SSDI21.58 ns12.66 ns56 B
Autofac354.18 ns271.40 ns1,720 B

Complex Graph Resolution

Container.NET 8.NET 10Allocated
MS.DI18.30 ns15.76 ns136 B
Grace17.81 ns16.09 ns136 B
DryIoc18.55 ns17.09 ns136 B
SimpleInj23.23 ns17.42 ns136 B
SSDI (eager)-19.42 ns136 B
SSDI (lazy)70.57 ns41.28 ns136 B
Autofac1,188.41 ns846.74 ns4,384 B

Container Setup (Registration)

Container.NET 8.NET 10Allocated
DryIoc1.03 μs0.82 μs4.0 KB
MS.DI1.33 μs1.42 μs12.4 KB
Grace4.87 μs4.23 μs21.3 KB
SimpleInj14.96 μs14.29 μs55.6 KB
Autofac16.73 μs14.48 μs73.8 KB
SSDI (lazy)18.28 μs26.91 μs30.7 KB
SSDI (eager)-10.40 ms485 KB

Note: SSDI supports two compilation modes:

  • Lazy (default) — Fast registration (~27μs), compiles factories on first Locate<T>() call. Best for hot-swapping and plugin systems.
  • Eager — Factories are pre-compiled during Configure() (~10ms), but resolution speed rivals top containers (~19ns). Set EagerCompilation = true.

License

MIT License - see LICENSE for details.

About

Super Simple Dependency Injection is a DI container that aims to be as fast as possible for high performance applications

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages