library.inversion.container.md 5.6 KB

Container Class

Overview

Container is the inversion of control container that manages component registrations and lifecycles. It stores registrations, manages singleton instances, creates scopes, and provides dependency resolution.

Namespace

Inversion

Class Declaration

public class Container : Object

Constructor

Container()

Creates a new container with empty registrations. The container automatically registers itself as a singleton.

var container = new Container();

Registration Methods

register<T>(owned FactoryDelegate factory_func, Lifecycle lifecycle)

Registers a type with a factory delegate and specified lifecycle. Returns a Registration for fluent configuration.

container.register<MyService>((scope) => new MyService(), Lifecycle.SINGLETON);

register_transient<T>(owned FactoryDelegate factory_func)

Registers a type as transient (new instance per resolve).

container.register_transient<MyService>((scope) => new MyService());

register_scoped<T>(owned FactoryDelegate factory_func)

Registers a type as scoped (one instance per scope).

container.register_scoped<MyService>((scope) => new MyService());

register_singleton<T>(owned FactoryDelegate factory_func)

Registers a type as singleton (one instance per container).

container.register_singleton<MyService>((scope) => new MyService());

register_startup<T>(owned FactoryDelegate factory_func)

Registers a type as startup (eagerly initialized singleton). Instance is created when initialise() is called.

container.register_startup<DatabaseConnection>((scope) => new DatabaseConnection());

register_type(Type implementation_type, owned FactoryDelegate factory_func, Lifecycle lifecycle)

Non-generic version for runtime type registration.

container.register_type(typeof(MyService), (scope) => new MyService(), Lifecycle.TRANSIENT);

register_factory_type(Type implementation_type, Factory factory, Lifecycle lifecycle)

Registers with a custom Factory instance.

var factory = new MyCustomFactory();
container.register_factory_type(typeof(MyService), factory, Lifecycle.SINGLETON);

register_factory<T>(Factory factory, Lifecycle lifecycle)

Generic version of factory registration.

container.register_factory<MyService>(custom_factory, Lifecycle.SCOPED);

Initialization Methods

initialise() throws Error

Eagerly instantiates all components registered with Lifecycle.STARTUP. Call this after all registrations are complete to ensure startup components are ready before the application runs.

container.register_startup<DatabaseConnection>((s) => new DatabaseConnection());
container.register_startup<CacheService>((s) => new CacheService());

// Initialize all startup components
try {
    container.initialise();
} catch (Error e) {
    // Handle initialization failure (e.g., database connection failed)
    error("Failed to initialize: %s", e.message);
}

Query Methods

is_registered(Type type) → bool

Checks if a type has any registrations.

if (container.is_registered(typeof(Logger))) {
    // Type is registered
}

get_registration(Type service_type) throws ContainerError → Registration

Gets any registration for a type. Throws ContainerError.NOT_REGISTERED if not found.

try {
    var reg = container.get_registration(typeof(IMyService));
} catch (ContainerError.NOT_REGISTERED e) {
    // Not registered
}

get_registrations(Type service_type) → Enumerable<Registration>

Gets all registrations for a type (may be empty).

var regs = container.get_registrations(typeof(Logger));
// Iterate over all Logger registrations

Scope Creation

create_scope() → Scope

Creates a new scope for scoped instance resolution.

var scope = container.create_scope();
var service = scope.resolve<MyService>();

create_transient_scope() → Scope

Creates a scope with transient lifecycle semantics.

var scope = container.create_transient_scope();

Internal Methods

get_or_create_singleton(Registration registration, Type requested_type) throws Error → Object

Gets existing singleton or creates new instance. Used internally by Scope during resolution.

Usage Example

var container = new Container();

// Register implementations
container.register_singleton<ConsoleLogger>((scope) => new ConsoleLogger())
    .as_type(typeof(ILogger));

container.register_scoped<UserService>((scope) => new UserService())
    .as_type(typeof(IUserService));

container.register_transient<RequestHandler>((scope) => new RequestHandler());

// Register startup components
container.register_startup<DatabaseConnection>((scope) => new DatabaseConnection());

// Initialize startup components
container.initialise();

// Create scope and resolve
var scope = container.create_scope();
var logger = scope.resolve<ILogger>();
var users = scope.resolve_all<IUserService>();

Multi-Registration

Multiple implementations can be registered for the same service type:

container.register_singleton<FileLogger>((s) => new FileLogger())
    .as_type(typeof(ILogger));
container.register_singleton<ConsoleLogger>((s) => new ConsoleLogger())
    .as_type(typeof(ILogger));

// Resolve all implementations
var scope = container.create_scope();
var all_loggers = scope.resolve_all<ILogger>();

The Container class is the central registry for Inversion IoC, providing registration methods for transient, scoped, singleton, and startup lifecycles, scope creation, and singleton instance management.