A lightweight dependency injection library for C# that combines simple DI container functionality with powerful source generation for content management.
- Attribute-based registration - Mark classes with
[Singleton],[Scoped], or[Transient] - Automatic service discovery - No manual registration required
- Constructor injection - Automatic dependency resolution
- Scope management - Built-in scoped service lifetime management
- Automatic enum generation - Creates enums from your content collections
- Type-safe access - Generated helper methods for accessing content by enum or index
- Performance optimized - Uses
NamedComparer<T>for fast dictionary lookups - Roslyn analyzers - Enforces best practices and catches common mistakes
dotnet add package SimpleInjectionMark your classes with lifetime attributes:
[Singleton] public class DatabaseService { public void Connect() => Console.WriteLine("Connected to database"); } [Scoped] public class UserService { private readonly DatabaseService _database; public UserService(DatabaseService database) { _database = database; } public void GetUser() => _database.Connect(); }Initialize and use the host:
var host = Host.Initialize(); // Get singleton services directly var dbService = host.Get<DatabaseService>(); // Create scopes for scoped services using var scope = host.CreateScope(); var userService = scope.Get<UserService>();Define your content classes:
// Your content item must implement INamed public record Material(string Name, string Color, int Durability) : INamed; // Your content collection must implement IContent<T> [Singleton] public partial class Materials : IContent<Material> { public Material[] All { get; } = [ new("Steel", "Gray", 100), new("Wood", "Brown", 50), new("Gold", "Yellow", 25) ]; }The source generator automatically creates:
// Generated enum public enum MaterialsType { Steel, Wood, Gold } // Generated helper methods public partial class Materials { public Material Get(MaterialsType type) => All[(int)type]; public Material this[MaterialsType type] => All[(int)type]; public Material GetById(int id) => All[id]; public Material Steel => All[0]; public Material Wood => All[1]; public Material Gold => All[2]; }Use the generated code:
var materials = host.Get<Materials>(); // Type-safe access using enums var steel = materials[MaterialsType.Steel]; var wood = materials.Get(MaterialsType.Wood); // Direct property access var gold = materials.Gold; // Index-based access var firstMaterial = materials.GetById(0);The library includes NamedComparer<T> for efficient dictionary operations with INamed keys:
// Use ToNamedDictionary extension method var materialDict = materials.All.ToNamedDictionary(m => m.Durability); // Or explicitly specify the comparer var dict = new Dictionary<Material, int>(new NamedComparer<Material>());For hierarchical content organization:
public class WeaponStats : ISubContent<Material, int> { public Dictionary<Material, int> ByKey { get; } public int this[Material material] => ByKey[material]; }The package includes analyzers that help you:
- NC001: Ensures
Dictionary<TKey, TValue>usesNamedComparer<T>forINamedkeys - TND001: Suggests using
ToNamedDictionary()instead ofToDictionary()forINamedkeys
- .NET 8.0 or .NET 9.0
- C# with nullable reference types enabled (recommended)
- Service Discovery: The host scans all loaded assemblies for classes marked with lifetime attributes
- Dependency Resolution: Constructor parameters are automatically resolved from registered services
- Source Generation: The generator scans for classes implementing
IContent<T>and generates enums and helper methods - Code Analysis: Roslyn analyzers ensure best practices for dictionary usage with named keys
- Use
[Singleton]for stateless services and shared resources - Use
[Scoped]for services that should be unique per operation/request - Use
[Transient]for lightweight, stateless services that need fresh instances - Always implement
INamedfor content objects to enable source generation - Use the generated enums for type-safe content access
- Leverage
ToNamedDictionary()for performance when working withINamedcollections
MIT License - see the license file for details.