Inyección de Dependencias
DependencyInjection
🌍 Idioma: English | Español
Contenedor IoC/DI para Delphi con una API fluida inspirada en Microsoft.Extensions.DependencyInjection de .NET. Registra servicios una vez, resuélvelos en cualquier parte — con tiempos de vida Singleton, Scoped y Transient.
¿Por qué usarlo?
- 🔌 API familiar — Los mismos métodos
AddSingleton/AddTransient/AddScopedque en .NET - 🎯 Genérico y type-safe — Verificación en tiempo de compilación mediante genéricos, sin tokens de cadena
- ⚡ Tres modos de vida — Singleton, Scoped (por scope) y Transient (nueva instancia siempre)
- 🏭 Registro flexible — Por clase, por lambda de factoría o por instancia existente
- 💤 Resolución diferida —
Lazy.From<T>()pospone la creación hasta el primer uso - 🦆 Duck Typing —
TDuckDecorator<T>envuelve cualquier objeto que implemente la misma forma de interfaz - 📦 Sin dependencias externas — Solo depende de
DependencyInjection.Abstractions
Inicio rápido
uses
Daf.Extensions.DependencyInjection,
Daf.DependencyInjection;
var
Services: IServiceCollection;
Provider: IServiceProvider;
begin
Services := TServiceCollection.Create;
// Registrar
Services.AddSingleton<IMyService, TMyService>;
// Construir el contenedor (congela la colección)
Provider := Services.BuildServiceProvider;
// Resolver
var Svc := Provider.GetRequiredService<IMyService>;
Svc.DoWork;
// Siempre hacer Shutdown al finalizar
Provider.ShutDown;
end;Sobrecargas de registro
// Por clase de implementación
Services.AddSingleton<IMyService, TMyServiceImpl>;
// Por lambda de factoría (control total)
Services.AddTransient<IMyService>(
function(P: IServiceProvider): IMyService
begin
Result := TMyServiceImpl.Create(P.GetRequiredService<IConfig>);
end);
// Por instancia existente (solo Singleton)
Services.AddSingleton<IMyService>(MyExistingInstance);Scopes
var Scope := Provider.CreateScope;
try
var Svc := Scope.ServiceProvider.GetRequiredService<IScopedService>;
// Las instancias Scoped son únicas dentro de este scope
finally
Scope := nil; // dispara Shutdown + limpieza gestionada
end;Patrón AppModule
Organiza los registros por módulo:
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;Consulta DependencyInjection.Abstractions para la interfaz IAppModule y todos los contratos clave.
Documentación
- 📖 Guía de uso — tiempos de vida, scopes, Lazy, DuckDecorator, integración con Hosting
Abstracciones
DependencyInjection.Abstractions
🌍 Idioma: English | Español
Contratos principales (interfaces y tipos) del sistema de Inyección de Dependencias de DAF. Este módulo no contiene implementación — define la forma de la que dependen los consumidores y que DependencyInjection implementa.
Qué hay en este módulo
| Unidad | Contenido |
|---|---|
Daf.Extensions.DependencyInjection |
IServiceCollection, IServiceProvider, IServiceScope, tiempos de vida, Factory, TDuckDecorator<T>, Lazy |
Daf.AppModule |
IAppModule — patrón de registro por módulo |
Daf.DependencyInjection.ActivatorUtilities |
Helpers para construir objetos mediante RTTI con argumentos resueltos por DI |
Tipos clave
IServiceCollection
Constructor fluido para registrar servicios antes de construir el contenedor.
Services
.AddSingleton<ICache, TMemoryCache>
.AddTransient<IRepo, TRepoImpl>
.AddScoped<IUoW, TDbUoW>;
var Provider := Services.BuildServiceProvider;IServiceProvider
El contenedor resuelto. Úsalo para obtener instancias de servicios.
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
Frontera de tiempo de vida. Los servicios Scoped se comparten dentro de un scope y se liberan cuando este termina.
var Scope := Provider.CreateScope;
var Svc := Scope.ServiceProvider.GetRequiredService<IScopedService>;
Scope := nil; // libera las instancias ScopedIAppModule
Convención para agrupar registros de servicios:
type
IAppModule = interface(IInvokable)
procedure AddServices(const Services: IServiceCollection);
end;Factory
Helper para construir un TServiceFactory desde una clase o instancia:
Services.Add(TypeInfo(IMyService), Singleton, Factory.From(TypeInfo(IMyService), TMyImpl));TDuckDecorator<T>
Clase base para envolver un servicio con lógica pre/post-llamada sin herencia. Sobreescribe BeforeCall / AfterCall.
Lazy
Result := Lazy.From<IHeavy>(Provider, function(P): IHeavy begin Result := THeavy.Create end);Dependencias
Este módulo no depende de ningún otro módulo DAF. Solo requiere la RTL de Delphi (System.Rtti, System.Generics.Collections).
La implementación está en DependencyInjection.