microsoft / tsyringe

Lightweight dependency injection container for JavaScript/TypeScript
MIT License
5.18k stars 172 forks source link

How to inject a mix of runtime value and normal dependencies #193

Open ericxinzhang opened 2 years ago

ericxinzhang commented 2 years ago

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:

Any suggestion / help will be really appreciated.

megastels commented 2 years ago

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

ericxinzhang commented 2 years ago

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.

MeltingMosaic commented 2 years ago

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().