Dependency Injection Integration
SimplEnteiner is itself a DI container, but it also plugs into Microsoft.Extensions.DependencyInjection (MS.DI) so it can be used as the backing container for ASP.NET Core, Generic Host, or any framework that consumes IServiceProvider/IServiceScopeFactory.
Source: Integrations/MS_DI/
Registration Entry Point
using Microsoft.Extensions.DependencyInjection;
using SimplEnteiner.Core;
using SimplEnteiner.Integrations.MS_DI;
IServiceCollection services = new ServiceCollection();
services.AddSimplEnteiner(container =>
{
container.Bind<IGreeter>().To<Greeter>().AsSingle().Apply();
container.Bind<IClock>().To<SystemClock>().AsScoped().Apply();
});
Extensions.AddSimplEnteiner (see Extensions.cs):
public static IServiceCollection AddSimplEnteiner(this IServiceCollection services, Action<DIContainer> configure)
{
DIContainer container = new DIContainer();
configure.ThrowIfArgumentNull().Invoke(container);
container.Build();
services.AddSingleton<IServiceProvider>(new SimplEnteinerServiceProvider(container));
services.AddSingleton<IServiceScopeFactory>(new SimplEnteinerServiceProvider(container));
return services;
}
Behavior notes:
- A brand-new
DIContaineris created, configured synchronously via theconfigurecallback, then immediatelyBuild()-ed — meaning all validation (dependency graph resolvability, generic constraint checks) happens before returning fromAddSimplEnteiner, so misconfiguration surfaces immediately at startup rather than lazily at first resolution. - Both
IServiceProviderandIServiceScopeFactoryare registered as singletons pointing to the sameSimplEnteinerServiceProviderinstance (which implements both interfaces plusISupportRequiredService). - This call does not remove or interact with any services already registered directly on the
IServiceCollectionviaservices.AddSingleton<T>()etc. — it purely adds anIServiceProvider/IServiceScopeFactorypair. Whether the host actually uses this custom provider depends on the hosting infra (e.g.UseServiceProviderFactoryin ASP.NET Core) — SimplEnteiner does not attempt to hijackIServiceCollectioninternals.
SimplEnteinerServiceProvider
SimplEnteinerServiceProvider.cs implements three MS.DI interfaces over a wrapped IScope:
public class SimplEnteinerServiceProvider : IServiceProvider, ISupportRequiredService, IServiceScopeFactory
{
public object GetService(Type serviceType) => _container.Resolve(serviceType);
public object GetRequiredService(Type serviceType) =>
_container.Resolve(serviceType) ?? throw new InvalidOperationException($"Service {serviceType} not registered.");
public IServiceScope CreateScope() => new SimplEnteinerServiceScope(_container.CreateScope());
}
GetServicesimply forwards toIScope.Resolve(Type). Any exception raised inside the SimplEnteiner resolution pipeline (e.g. "No binding found for X") propagates unchanged — MS.DI'sGetServicecontract nominally expectsnullfor unresolvable optional services, so callers relying on gracefulnullreturns for unregistered types should be aware SimplEnteiner throws instead for types that are not concrete classes and have no binding (see Resolution Workflow).CreateScope()delegates toIScope.CreateScope(), producing a genuine hierarchical child scope (not just an MS.DI-style logical scope) — singletons remain shared with the root, scoped services get fresh instances per created scope, exactly matching SimplEnteiner's own scope semantics.
SimplEnteinerServiceScope
SimplEnteinerServiceScope.cs wraps a child IScope inside a new SimplEnteinerServiceProvider and exposes it via the standard IServiceScope.ServiceProvider property. Disposing the IServiceScope disposes the underlying provider (if disposable), which in turn is expected to be released by the owning scope's lifetime management.
Integration Diagram
sequenceDiagram
participant Host as ASP.NET Core / Generic Host
participant Ext as Extensions.AddSimplEnteiner
participant Container as DIContainer
participant Provider as SimplEnteinerServiceProvider
participant Scope as IScope (child)
Host->>Ext: services.AddSimplEnteiner(configure)
Ext->>Container: new DIContainer()
Ext->>Container: configure(container)
Ext->>Container: Build()
Ext->>Provider: new SimplEnteinerServiceProvider(container)
Ext->>Host: services.AddSingleton<IServiceProvider>(Provider)
Ext->>Host: services.AddSingleton<IServiceScopeFactory>(Provider)
Host->>Provider: CreateScope()
Provider->>Container: CreateScope()
Container-->>Provider: child IScope
Provider->>Scope: wrap in SimplEnteinerServiceScope
Host->>Provider: GetService(typeof(IMyService))
Provider->>Container: Resolve(typeof(IMyService))
Container-->>Provider: instance
Provider-->>Host: instance
Limitations of the Current Integration
- There is no automatic translation of services already registered on the
IServiceCollection(viaAddSingleton,AddScoped, etc.) into SimplEnteiner bindings — all bindings must be configured explicitly inside theconfigurecallback passed toAddSimplEnteiner. IServiceProviderIsServiceand other newer MS.DI diagnostic interfaces are not implemented.- Keyed services (
IServiceCollectionkeyed registration APIs) are not directly mapped; SimplEnteiner's ownWithId(...)/[Id]mechanism is a related but separate concept (see API Reference → Attributes and Delegates).
Continue to API Reference → Container and Scope.