Dependency Injection
DependencyInjection
🌍 Language: English | Español
IoC/DI container for Delphi with a fluent API inspired by .NET’s Microsoft.Extensions.DependencyInjection. Register services once, resolve them anywhere — with Singleton, Scoped, and Transient lifetimes.
Why use this?
- 🔌 Familiar API — Same
AddSingleton/AddTransient/AddScopedpattern as .NET - 🎯 Generic & type-safe — Compile-time verification via generics, no string tokens
- ⚡ Three lifetime modes — Singleton, Scoped (per scope), Transient (new every time)
- 🏭 Flexible registration — By class, by factory lambda, or by existing instance
- 💤 Lazy resolution —
Lazy.From<T>()defers creation until first use - 🦆 Duck Typing —
TDuckDecorator<T>wraps any object implementing the same interface shape - 📦 Zero external deps — Depends only on
DependencyInjection.Abstractions
Quick Start
uses
Daf.Extensions.DependencyInjection,
Daf.DependencyInjection;
var
Services: IServiceCollection;
Provider: IServiceProvider;
begin
Services := TServiceCollection.Create;
// Register
Services.AddSingleton<IMyService, TMyService>;
// Build the container (freezes the collection)
Provider := Services.BuildServiceProvider;
// Resolve
var Svc := Provider.GetRequiredService<IMyService>;
Svc.DoWork;
// Always shut down when done
Provider.ShutDown;
end;Registration overloads
// By implementation class
Services.AddSingleton<IMyService, TMyServiceImpl>;
// By factory lambda (full control)
Services.AddTransient<IMyService>(
function(P: IServiceProvider): IMyService
begin
Result := TMyServiceImpl.Create(P.GetRequiredService<IConfig>);
end);
// By existing instance (Singleton only)
Services.AddSingleton<IMyService>(MyExistingInstance);Scopes
var Scope := Provider.CreateScope;
try
var Svc := Scope.ServiceProvider.GetRequiredService<IScopedService>;
// Scoped instances are unique within this scope
finally
Scope := nil; // triggers Shutdown + managed cleanup
end;AppModule pattern
Organise registrations by module:
type
TMyModule = class(TInterfacedObject, IAppModule)
procedure AddServices(const Services: IServiceCollection);
end;
procedure TMyModule.AddServices(const Services: IServiceCollection);
begin
Services.AddSingleton<IMyService, TMyService>;
Services.AddTransient<IOther, TOtherImpl>;
end;See DependencyInjection.Abstractions for the IAppModule interface and all core contracts.
Documentation
- 📖 Usage Guide — lifetimes, scopes, Lazy, DuckDecorator, integration with Hosting
Abstractions
DependencyInjection.Abstractions
🌍 Language: English | Español
Core contracts (interfaces and types) for the DAF Dependency Injection system. This module contains no implementation — it defines the shape that consumers depend on and that DependencyInjection implements.
What’s in this module
| Unit | Contents |
|---|---|
Daf.Extensions.DependencyInjection |
IServiceCollection, IServiceProvider, IServiceScope, lifetimes, Factory, TDuckDecorator<T>, Lazy |
Daf.AppModule |
IAppModule — module registration pattern |
Daf.DependencyInjection.ActivatorUtilities |
Helpers to construct objects via RTTI with DI-resolved arguments |
Key types
IServiceCollection
Fluent builder for registering services before the container is built.
Services
.AddSingleton<ICache, TMemoryCache>
.AddTransient<IRepo, TRepoImpl>
.AddScoped<IUoW, TDbUoW>;
var Provider := Services.BuildServiceProvider;IServiceProvider
The resolved container. Use it to obtain service instances.
var Svc := Provider.GetRequiredService<IMyService>;
var Opt: IMyService;
if Provider.TryGet<IMyService>(Opt) then ...
var All := Provider.GetServices<IPlugin>;TServiceLifeTime
type TServiceLifeTime = (Singleton, Scoped, Transient);IServiceScope
A lifetime boundary. Scoped services are shared within a scope and released when the scope ends.
var Scope := Provider.CreateScope;
var Svc := Scope.ServiceProvider.GetRequiredService<IScopedService>;
Scope := nil; // releases scoped instancesIAppModule
Convention for grouping service registrations:
type
IAppModule = interface(IInvokable)
procedure AddServices(const Services: IServiceCollection);
end;Factory
Helper to build TServiceFactory from a class or instance:
Services.Add(TypeInfo(IMyService), Singleton, Factory.From(TypeInfo(IMyService), TMyImpl));TDuckDecorator<T>
Base class for wrapping a service with pre/post-call logic without inheritance. Override BeforeCall / AfterCall.
Lazy
Result := Lazy.From<IHeavy>(Provider, function(P): IHeavy begin Result := THeavy.Create end);Dependency
This module has no dependencies on other DAF modules. It depends only on the Delphi RTL (System.Rtti, System.Generics.Collections).
The implementation is in DependencyInjection.