Skip to main content
Version: 8.x

Container

The InversifyJS container is where dependencies are first configured through binding and, possibly later, reconfigured and removed. The container can be worked on directly in this regard or container modules can be utilized. You can query the configuration and resolve configured dependencies with the get methods. You can react to resolutions with container activation handlers and unbinding with container deactivation handlers. You can create container hierarchies where container ascendants can supply the dependencies for descendants. For testing, state can be saved as a snapshot on a stack and later restored.

Container Options​

Container options can be passed to the Container constructor, and defaults will be provided if you do not or if you do but omit an option. Options can be changed after construction and will be shared by child containers created from the Container if you do not provide options for them.

autobind​

autobind?: true;

Option to automatically bind unbound class services to themselves. Whenever an instance is resolved, the container attempts to add a binding if no binding is found for the requested service.

parent​

parent?: Container | undefined;

The parent container, if any. Refer to the container hierarchy docs for more information.

defaultScope​

defaultScope?: BindingScope | undefined;

The default scope for bindings.

bind​

bind<T>(serviceIdentifier: ServiceIdentifier<T>): BindToFluentSyntax<T>

Sets a new binding.

info

Unless specified otherwise, binding scopes are transient by default.

get​

get<T>(serviceIdentifier: ServiceIdentifier<T>, options: OptionalGetOptions): T | undefined;
get<T>(serviceIdentifier: ServiceIdentifier<T>, options?: GetOptions): T;

Resolves a dependency by its runtime identifier. The runtime identifier must be associated with only one binding and the binding must be synchronously resolved, otherwise an error is thrown.

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);

const katana: Weapon = container.get<Weapon>('Weapon');

getAsync​

getAsync<T>(serviceIdentifier: ServiceIdentifier<T>, options: OptionalGetOptions): Promise<T | undefined>;
getAsync<T>(serviceIdentifier: ServiceIdentifier<T>, options?: GetOptions): Promise<T>;

Resolves a dependency by its runtime identifier. The runtime identifier must be associated with only one binding, otherwise an error is thrown.

async function buildLevel1(): Promise<Level1> {
return new Level1();
}

const container: Container = new Container();
container
.bind('Level1')
.toDynamicValue(async (): Promise<Level1> => buildLevel1());

const level1: Promise<Level1> = container.getAsync<Level1>('Level1');

getAll​

getAll<T>(serviceIdentifier: ServiceIdentifier<T>, options?: GetAllOptions): T[];

Get all available bindings for a given identifier. All the bindings must be synchronously resolved, otherwise an error is thrown:

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
container.bind<Weapon>('Weapon').to(Shuriken);

// returns Weapon[] with both Katana and Shuriken instances
const weapons: Weapon[] = container.getAll<Weapon>('Weapon');

getAllAsync​

getAllAsync<T>(serviceIdentifier: ServiceIdentifier<T>, options?: GetAllOptions): Promise<T[]>

Get all available bindings for a given identifier:

const container: Container = new Container();
container.bind<Weapon>('Weapon').toDynamicValue(async () => new Katana());
container.bind<Weapon>('Weapon').to(Shuriken);

const weapons: Promise<Weapon[]> = container.getAllAsync<Weapon>('Weapon');

isBound​

isBound(serviceIdentifier: ServiceIdentifier<unknown>, options?: IsBoundOptions): boolean;

You can use the isBound method to check if there are registered bindings for a given service identifier.

interface Warrior {
kind: string;
}

const katanaSymbol: symbol = Symbol.for('Katana');
const warriorSymbol: symbol = Symbol.for('Warrior');

@injectable()
class Ninja implements Warrior {
public readonly kind: string = 'ninja';
}

@injectable()
class Katana {}

const container: Container = new Container();
container.bind<Warrior>(Ninja).to(Ninja);
container.bind<Warrior>(warriorSymbol).to(Ninja);

// returns true
const isNinjaBound: boolean = container.isBound(Ninja);
// returns true
const isWarriorSymbolBound: boolean = container.isBound(warriorSymbol);
// returns false
const isKatanaBound: boolean = container.isBound(Katana);
// returns false
const isKatanaSymbolBound: boolean = container.isBound(katanaSymbol);

isCurrentBound​

isCurrentBound(serviceIdentifier: ServiceIdentifier<unknown>, options?: IsBoundOptions): boolean;

You can use the isCurrentBound method to check if there are registered bindings for a given service identifier only in the current container.

interface Warrior {
kind: string;
}

const katanaSymbol: symbol = Symbol.for('Katana');
const warriorSymbol: symbol = Symbol.for('Warrior');

@injectable()
class Ninja implements Warrior {
public readonly kind: string = 'ninja';
}

@injectable()
class Katana {}

const container: Container = new Container();
container.bind<Warrior>(Ninja).to(Ninja);
container.bind<Warrior>(warriorSymbol).to(Ninja);

const containerChild: Container = new Container({ parent: container });

containerChild.bind<Katana>(Katana).to(Katana);
containerChild.bind<Katana>(katanaSymbol).to(Katana);

// returns false
const isNinjaBound: boolean = containerChild.isCurrentBound(Ninja);
// returns false
const isWarriorSymbolBound: boolean =
containerChild.isCurrentBound(warriorSymbol);
// returns true
const isKatanaBound: boolean = containerChild.isCurrentBound(Katana);
// returns true
const isKatanaSymbolBound: boolean =
containerChild.isCurrentBound(katanaSymbol);

load​

load(...modules: ContainerModule[]): void;

Calls the registration method of each module synchronously. Will throw an error if any module loading would be asynchronous. See ContainerModule API docs.

loadAsync​

loadAsync(...modules: ContainerModule[]): Promise<void>;

Asynchronous version of load. Calls the registration method of each module. See ContainerModule API docs.

onActivation​

onActivation<T>(serviceIdentifier: ServiceIdentifier<T>, onActivation: BindingActivation<T>): void;

Adds an activation handler for all services associated to the service identifier.

interface Weapon {
damage: number;
}

export class Katana implements Weapon {
#damage: number = 10;

public get damage(): number {
return this.#damage;
}

public improve(): void {
this.#damage += 2;
}
}

const container: Container = new Container();
container.bind<Weapon>('Weapon').to(Katana);
container.onActivation(
'Weapon',
(_context: ResolutionContext, katana: Katana): Katana | Promise<Katana> => {
katana.improve();

return katana;
},
);

// Katana.damage is 12
const katana: Weapon = container.get<Weapon>('Weapon');

onDeactivation​

onDeactivation<T>(serviceIdentifier: ServiceIdentifier<T>, onDeactivation: BindingDeactivation<T>): void;

Adds a deactivation handler for a service identifier.

interface Weapon {
damage: number;
}

class Katana implements Weapon {
readonly #damage: number = 10;

public get damage(): number {
return this.#damage;
}
}

const container: Container = new Container();

container.bind<Weapon>('Weapon').to(Katana).inSingletonScope();

container.get('Weapon');

container.onDeactivation('Weapon', (weapon: Weapon): void | Promise<void> => {
console.log(`Deactivating weapon with damage ${weapon.damage.toString()}`);
});

container.unbind('Weapon');

rebind​

rebind<T>(serviceIdentifier: ServiceIdentifier<T>): BindToFluentSyntax<T>;

Convenience method that unbinds a service identifier synchronously and then creates a new binding for it. This is equivalent to calling container.unbind(serviceId) followed by container.bind(serviceId), but in a single method. Returns a binding builder to continue configuring the new binding.

const container: Container = new Container();

// Create initial binding
container.bind<Weapon>('Weapon').to(Katana);

// Get instance of Katana
const katana: Weapon = container.get<Weapon>('Weapon');
console.log(katana.damage); // 10

// Rebind synchronously to Shuriken
// This returns a BindToFluentSyntax to continue configuring the binding
container.rebind<Weapon>('Weapon').to(Shuriken);

// Get instance of Shuriken
const shuriken: Weapon = container.get<Weapon>('Weapon');
console.log(shuriken.damage);

rebindAsync​

rebindAsync<T>(serviceIdentifier: ServiceIdentifier<T>): Promise<BindToFluentSyntax<T>>;

Asynchronous version of rebind. Unbinds a service identifier and then creates a new binding for it. Returns a binding builder to continue configuring the new binding.

const container: Container = new Container();

// Create initial binding
container.bind<Weapon>('Weapon').to(Katana);

// Get instance of Katana
const katana: Weapon = container.get<Weapon>('Weapon');
console.log(katana.damage); // 10

// Rebind asynchronously to Shuriken
async function rebindWeapon() {
// First unbind the existing service
container.unbind('Weapon');

// Then bind to the new service
container.bind<Weapon>('Weapon').to(Shuriken);

// Get instance of Shuriken
const shuriken: Weapon = container.get<Weapon>('Weapon');
console.log(shuriken.damage); // 8
}

// Call the async function
void rebindWeapon();

register​

register(pluginConstructor: Newable): void;

Registers a plugin to extend the container's functionality. The plugin must extend the Plugin class from @inversifyjs/plugin and respect its constructor signature. Refer to the plugin docs for more information.

restore​

restore(): void;

Restore container state to last snapshot. Refer to the docs for more information.

snapshot​

snapshot(): void;

Save the state of the container to be later restored with the restore method. Refer to the docs for more information.

unbind​

unbind(identifier: BindingIdentifier | ServiceIdentifier): void;

Removes bindings from the container synchronously. When passed:

  • A service identifier: removes all bindings bound to that service identifier
  • A binding identifier: removes the specific binding associated with that identifier

This will result in the deactivation process.

const container: Container = new Container();

// Create a binding
container.bind<Weapon>('Weapon').to(Katana);

// Check if it's bound
console.log(container.isBound('Weapon')); // true

// Synchronously unbind the service
container.unbind('Weapon');

// Verify it's unbound
console.log(container.isBound('Weapon'));

Example: Unbind a binding by its identifier​

const bindingIdentifier: BindingIdentifier = container
.bind('MyService')
.to(MyServiceImpl)
.getIdentifier();

// Later, unbind just this specific binding
container.unbind(bindingIdentifier);

unbindAsync​

unbindAsync(identifier: BindingIdentifier | ServiceIdentifier): Promise<void>;

Asynchronous version of unbind. Removes bindings from the container. When passed:

  • A service identifier: removes all bindings bound to that service identifier
  • A binding identifier: removes the specific binding associated with that identifier

This will result in the deactivation process.

unbindAll​

unbindAll(): void;

Removes all bindings in this container synchronously. This will result in the deactivation process.

unbindAllAsync​

unbindAllAsync(): Promise<void>;

Asynchronous version of unbindAll. Removes all bindings in this container. This will result in the deactivation process.

unload​

unload(...modules: ContainerModule[]): void;

Removes bindings and handlers added by the modules synchronously. This will result in the deactivation process. See ContainerModule API docs.

unloadAsync​

unloadAsync(...modules: ContainerModule[]): Promise<void>;

Asynchronous version of unload. Removes bindings and handlers added by the modules. This will result in the deactivation process. See ContainerModule API docs.

GetOptions​

Options that can be passed to the get, getAll, getAsync, and getAllAsync methods.

interface GetOptions {
autobind?: boolean;
name?: MetadataName;
optional?: boolean;
tag?: GetOptionsTagConstraint;
}
  • autobind (boolean): Option to automatically bind unbound class services to themselves.
  • name (MetadataName): The name metadata to match bindings.
  • optional (boolean): If true, the method will return undefined or empty array if no binding is found.
  • tag (GetOptionsTagConstraint): The tag metadata to match bindings.

OptionalGetOptions​

Options that can be passed to the get and getAsync methods when the result is optional.

interface OptionalGetOptions extends GetOptions {
optional: true;
}
  • optional (true): Indicates that the result is optional and the method will return undefined if no binding is found.

IsBoundOptions​

Options that can be passed to the isBound and isCurrentBound methods.

interface IsBoundOptions {
name?: MetadataName;
tag?: GetOptionsTagConstraint;
}
  • name (MetadataName): The name metadata to match bindings.
  • tag (GetOptionsTagConstraint): The tag metadata to match bindings.

GetAllOptions​

Options that can be passed to the getAll and getAllAsync methods.

interface GetAllOptions extends GetOptions {
chained?: boolean;
}
  • chained (boolean): Option to enable chained resolution across container hierarchies. Refer to the docs for more information.