0

The inversify-express-utils README contains the following example on request-scoped services.

I am trying to implement something similar for a Koa application, however, I struggle to understand how the hierarchical DI in this example works.

import { inject, injectable } from "inversify";
import { BaseHttpController, BaseMiddleware, controller, httpGet } from "inversify-express-utils";
import * as express from "express";

const TYPES = {
    TraceId: Symbol.for("TraceIdValue"),
    TracingMiddleware: Symbol.for("TracingMiddleware"),
    Service: Symbol.for("Service"),
};

@injectable()
class TracingMiddleware extends BaseMiddleware {

    public handler(
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ) {
        this.bind<string>(TYPES.TraceIdValue)
            .toConstantValue(`${ req.header('X-Trace-Id') }`);

        next();
    }
}

@controller("/")
class TracingTestController extends BaseHttpController {

    constructor(@inject(TYPES.Service) private readonly service: Service) {
        super();
    }

    @httpGet(
        "/",
        TYPES.TracingMiddleware
    )
    public getTest() {
        return this.service.doSomethingThatRequiresTheTraceID();
    }
}

@injectable()
class Service {
    constructor(@inject(TYPES.TraceIdValue) private readonly traceID: string) {
    }

    public doSomethingThatRequiresTheTraceID() {
        // ...
    }
}

From reading the docs and code I understand that each Express request handler has a HttpContext attached to it, which in turn has a child DI container attached.

The example suggests that the traceID dependency of the Service class is resolved from that child container attached to the httpContext in the Express request.

However, I do not understand how it is made sure that traceID is being resolved from the child container and not from the parent or root container?

Tobi
  • 1,492
  • 1
  • 13
  • 20
  • I think I found the [magic line of code](https://github.com/inversify/inversify-express-utils/blob/bc40bb7671e0d4d8183266b3b3d563bb62056618/src/server.ts#L253): `httpContext.container.getNamed(TYPE.Controller, controllerName)[key](...args)` It is here where the controller is being resolved **from the child container** and hence the the `traceId` dependency is also resolved from the child container. I believe this is the missing piece that I was looking for. – Tobi Apr 10 '20 at 07:06

1 Answers1

1

The magic line of code:

httpContext.container.getNamed<any>(TYPE.Controller, controllerName)[key](...args)

It is here where the controller is being resolved from the child container and hence the the traceId dependency is also resolved from the child container.

Tobi
  • 1,492
  • 1
  • 13
  • 20