---
url: https://node-ts.github.io/bus/guide/dependency-injection.md
description: >-
  Give handlers their dependencies with closures, or resolve class handlers and
  workflows from your IoC container.
---

# Dependency injection

Handlers need dependencies such as repositories and API clients. This page covers the two ways to give them those: closures, which need nothing extra, and an adapter to an IoC container, for class handlers and workflows.

## With closures

A function handler gets its dependencies from the scope it's declared in. To swap them in tests, declare the handler in a function that takes them:

```ts
interface PaymentGateway {
  charge(creditCardToken: string, amount: number): Promise<void>
}

// Dependencies reach a function handler through a closure
export const chargeCreditCardHandler = (gateway: PaymentGateway) =>
  handlerFor(ChargeCreditCard, async command =>
    gateway.charge(command.creditCardToken, command.amount)
  )
```

A handler doesn't need the bus injected to send or publish: it uses its [`HandlerContext`](/api/bus-core/interfaces/HandlerContext), which is bound to the bus that received the message.

## With a container

Class handlers and class workflows are constructed for each message. Without a container, the bus constructs them with `new` and no arguments, and `build()` throws `ContainerNotRegistered` for a class handler whose constructor takes some.

```ts
export class ChargeCreditCardHandler implements Handler<ChargeCreditCard> {
  constructor(private readonly gateway: PaymentGateway) {}

  get messageType() {
    return ChargeCreditCard
  }

  async handle(command: ChargeCreditCard) {
    await this.gateway.charge(command.creditCardToken, command.amount)
  }
}
```

To construct them with their dependencies, pass an adapter to your IoC container with `withContainer()`. It has one method, `get`, which returns an instance of the class it's given. This example works with [inversify](https://www.npmjs.com/package/inversify), or any container that resolves instances by class:

```ts
const bus = Bus.configure()
  .withMessageTypes(messageTypes)
  .withHandler(ChargeCreditCardHandler)
  .withContainer({
    get: <T>(type: ClassConstructor<T>) => container.get<T>(type)
  })
  .build()
```

`get` is also given the message being handled and its attributes, for containers that resolve differently per message, and may return a promise.

## See also

* [Commands](/guide/messages/commands), for class handlers
* [`ContainerAdapter`](/api/bus-core/interfaces/ContainerAdapter) in the API reference
