microsoft/tsyringe

How to inject a mix of runtime value and normal dependencies

ericxinzhang opened this issue ยท 3 comments

I'd like to implement something like the following:

A orchestration service whose constructor accepts dependency services (can be injected using @inject decorator) and a runtime value:

@injectable()
class OrchestrationService {
  constructor(
    @inject(ServiceA) private dependencyA: ServiceA,
    @inject(ServiceA) private dependencyB: ServiceB,
    runtimeValue: string,
  ) {
    this.init(runtimeValue);
  }
}

And then I can somehow resolve the instance using the runtime value:

const orchestrationService = container.resolve<OrchestrationService>(runtimeValue);

I think I have two problems here:

  • How to resolve the instance based on a runtime value which cannot be registered beforehand.
  • How to inject the runtime value as one of the dependencies into the constructor.

Any suggestion / help will be really appreciated.

you can register value in container

const SomeToken:InjectionToken<string> = "MyToken";

class Service{
  constructor(
    @inject(ServiceA) private dependencyA: ServiceA,
    @inject(ServiceA) private dependencyB: ServiceB,
    @inject(SomeToken) runtimeValue: string,
  )
}

container.registerInstance(SomeToken, "runtimeValue");
container.resolve(SomeToken); // runtimeValue
container.resolve(Service); // Service instance

https://github.com/microsoft/tsyringe#injecting-primitive-values-named-injection

you can register value in container

const SomeToken:InjectionToken<string> = "MyToken";

class Service{
  constructor(
    @inject(ServiceA) private dependencyA: ServiceA,
    @inject(ServiceA) private dependencyB: ServiceB,
    @inject(SomeToken) runtimeValue: string,
  )
}

container.registerInstance(SomeToken, "runtimeValue");
container.resolve(SomeToken); // runtimeValue
container.resolve(Service); // Service instance

https://github.com/microsoft/tsyringe#injecting-primitive-values-named-injection

Thank you. Registering the runtime value at runtime just before resolving looks a bit weird but I reckon that's the best we can get.

I think that @autoInjectable() allows for this kind of behavior (so you could do new OrchestrationService(runtimeParam)), but it wouldn't work with container.resolve().