Skip to main content
Version: 4.x

Container

ExpressoTS uses an IoC Container for dependency injection, making it easy to manage object creation, resolution, and lifecycle.

Configuration Options​

Interface Definition​

interface ContainerOptions {
defaultScope?: "Request" | "Singleton" | "Transient";
skipBaseClassChecks?: boolean;
autoBindInjectable?: boolean;
}

Default Values​

  • defaultScope: "Request" (creates new instance per HTTP request)
  • autoBindInjectable: true (automatically binds @injectable classes)
  • skipBaseClassChecks: false (validates class inheritance)

Options Reference​

defaultScope​

Controls the default lifecycle for all bindings in the container.

ScopeLifecyclePerformanceUse CaseMemory
RequestNew per requestFastStateless services (default)Low
SingletonSingle instanceFastestDB connections, configHigh
TransientNew every injectionSlowestPure functions, disposableHighest

skipBaseClassChecks​

What it does: Controls D.I base class inheritance validation.

Performance Impact:

  • false (default): Container creation ~15-20ms, validates inheritance
  • true: Container creation ~8-12ms, 40-50% faster, runtime validation only

When to enable:

  • Production environment after thorough testing
  • Large applications with many classes
  • Confident in class hierarchy correctness

When to disable:

  • Development environment
  • Debugging DI issues
  • Complex inheritance hierarchies

autoBindInjectable​

What it does: Automatically binds classes decorated with @injectable()

Performance Impact:

  • true (default): No explicit binding needed, cleaner code
  • false: Must explicitly bind every service, more control

When to disable:

  • Need explicit control over all bindings
  • Debugging binding conflicts
  • Large teams requiring strict binding rules

Creating the Container​

Basic Setup​

export class App extends AppExpress {
private container: AppContainer = this.configContainer([AppModule]);

globalConfiguration(): void {}
}

With Custom Options​

import { Scope } from "@expressots/core";

private container: AppContainer = this.configContainer([AppModule], {
defaultScope: Scope.Singleton,
autoBindInjectable: true,
skipBaseClassChecks: true
});

Introspection API​

ExpressoTS v4 provides a comprehensive introspection API for container bindings, designed for debugging, analysis, and integration with ExpressoTS Studio.

Getting Bindings Data​

Retrieve structured data about all container bindings:

// Get all bindings as structured data
const bindings = this.container.getBindingsInfo();

bindings.forEach((b) => {
console.log(`${b.serviceIdentifier}: ${b.scope} (${b.type})`);
});

Each binding includes:

PropertyDescription
serviceIdentifierClass name, symbol, or string token
scopeRequest, Singleton, Transient, custom
typeConstructor, ConstantValue, Factory
cachedWhether instance is cached
activatedWhether binding has been resolved
moduleIdModule the binding belongs to

Filtering Bindings​

Query bindings with specific criteria:

// Get only singleton bindings
const singletons = this.container.filterBindings({ scope: "Singleton" });

// Get cached bindings
const cached = this.container.filterBindings({ cached: true });

// Find by identifier pattern
const controllers = this.container.filterBindings({ identifier: "Controller" });

// Combine filters
const activeSingletons = this.container.filterBindings({
scope: "Singleton",
activated: true,
});

Summary Statistics​

Get aggregate statistics about container bindings:

const summary = this.container.getBindingsSummary();

console.log(`Total bindings: ${summary.total}`);
console.log(`Singletons: ${summary.byScope["Singleton"] || 0}`);
console.log(`Cached: ${summary.cached}`);
console.log(`Activated: ${summary.activated}`);

Formatted View​

Get a formatted string representation:

// Print formatted view to console
console.log(this.container.getFormattedBindingsView());

// With filters
console.log(this.container.getFormattedBindingsView({ scope: "Singleton" }));

Complete Introspection​

Get all container data in a single call (ideal for ExpressoTS Studio):

const data = this.container.introspect();

// Structure:
// {
// bindings: BindingInfo[],
// summary: BindingsSummary,
// options: ContainerOptions,
// timestamp: string,
// containerId: number
// }

Legacy: Table View​

For quick debugging, the table view is still available:

this.container.viewContainerBindings();

Container Bindings View

Getting Container Options​

Inspect current configuration:

const options = this.container.getContainerOptions();
console.log(options.defaultScope);
console.log(options.autoBindInjectable);

Accessing Raw Container​

For advanced D.I operations:

const inversifyContainer = this.container.Container;
// Use D.I APIs directly

Performance Best Practices​

Production Optimization​

import { Scope } from "@expressots/core";

private container: AppContainer = this.configContainer([AppModule], {
defaultScope: Scope.Request,
skipBaseClassChecks: true, // 40-50% faster
autoBindInjectable: true
});

Memory Considerations​

  • Singleton: Lives for application lifetime
  • Request: Cleaned up after request completes
  • Transient: Creates memory churn if overused

Troubleshooting​

Common Issues​

DI Resolution Errors

  • Use getBindingsInfo() or filterBindings() to inspect registrations
  • Use introspect() for complete container state
  • Verify @injectable() decorator is present
  • Check for missing module registration

Performance Issues

  • Use getBindingsSummary() to analyze scope distribution
  • Consider enabling skipBaseClassChecks in production
  • Review scope usage (too many Transient?)

Binding Conflicts

  • Use filterBindings({ identifier: 'YourService' }) to find duplicates
  • Use getContainerOptions() to inspect config
  • Use isBound() before binding in modules

Support the Project​

ExpressoTS is MIT-licensed open source. See the support guide to contribute.