0

I've been looking if it's possible for TSyringe to inject all classes that implements some interface (or extends from an abstract class), like this:

@injectable()
export interface IService {
    foo(): void;
}

@injectable()
export class Service1 implements IService {
    foo() { console.out("bar"); }
}

@injectable()
export class Service2 implements IService {
    foo() { console.out("baz"); }
}

export class CollectorService {
    constructor(
        @inject('Service')
        services: IService[]
    ) {
        services.forEach(s => s.foo());
    }
}

I just started using TSyringe a month ago, so I'm not familiar with all features and I don't know how to register this kind of dependency (if it's possible to achieve what I'm proposing) in the DI container. I'm trying to mimic Spring @Autowire annotation.

2 Answers2

1

I don't know if it's the best solution, but I could achieve multiple injection with this:

import {
  injectable, injectAll, registry, container,
} from 'tsyringe';

interface ValueClass {
  value: string;

  sayMyValue(): void;
}

@injectable()
@registry([{ token: 'ValueClass', useClass: ValueClass1 }])
class ValueClass1 implements ValueClass {
  sayMyValue(): void {
    console.log('ValueClass1');
  }

  value: string = 'value1';
}

@injectable()
@registry([{ token: 'ValueClass', useClass: ValueClass2 }])
class ValueClass2 implements ValueClass {
  value: string;

  sayMyValue(): void {
    console.log('ValueClass2');
  }
}

@injectable()
export class AppClass {
  constructor(
    @injectAll('ValueClass')
    private valueClasses: ValueClass[],
  ) { }

  run() {
    this.valueClasses
      .forEach((valueClass: ValueClass) => { valueClass.sayMyValue(); });
  }
}

const v = container.resolve(AppClass);
v.run();
0

I couldn't get the registry per class to work as in Aníbal Deboni Neto asnwer, but using an proxy class to place all the registries worked for me. I also used a Symbol so that I don't have any magic strings.

interface IBar {}

@injectable()
class Foo implements IBar {}
@injectable()
class Baz implements IBar {}

@registry([
  {token: Bar.token, useToken: Foo},
  {token: Bar.token, useToken: Baz}
])
abstract class Bar {
  static readonly token = Symbol("IBar");
}

@injectable()
class User{
  constructor(@injectAll(Bar.token) private bars: IBar[]) {
  }
}

const bars: IBar[] = container.resolveAll<IBar>(Bar.token);
const user: User = container.resolve(User);

Source: https://github.com/microsoft/tsyringe#register

Barnstokkr
  • 2,904
  • 1
  • 19
  • 34