Обратный цикл 4 — не удается получить метаданные из массива классов, введенных с помощью @inject.tag()

#typescript #loopbackjs #loopback4

#машинописный текст #loopbackjs #петлевая привязка4 #typescript #обратный цикл 4

Вопрос:

Есть ли пара классов, зарегистрированных в качестве сервисов:

 @processor('some_value')
export class MyService {}

@processor('another_value')
export class AnotherService {}
  

Эти сервисы оформлены с помощью декоратора processor(), определенного следующим образом:

 const PROCESSOR_CLASS_META = MetadataAccessor.create<
    string,
    ClassDecorator
  >('processor-decorator-metadata');

export function processor(value): ClassDecorator {
  return (
    target: Function amp; {value?: string},
  ) => {
    bind({tags: 'processor'})(target);

    const decorator = ClassDecoratorFactory.createDecorator(
      PROCESSOR_CLASS_META,
      value,
      {decoratorName: '@processor'},
    );
    decorator(target);
  };
}

  

Декоратор выполняет две вещи — помечает класс как «процессор» и устанавливает string тип метаданных.

Теперь у меня есть третья услуга. В этой службе я внедряю все службы с тегом «процессор» следующим образом:

 export class consumerService {
  constructor(
    @inject.tag('processor')
    private readonly processorClasses: Constructor<Function>,
  )
}
  

Когда я пытаюсь получить метаданные введенных классов, я получаю undefined :

 export class consumerService {
  constructor(
    @inject.tag('processor')
    private readonly processorClasses: Constructor<Function>,
  )
  
  public getMetaData() {
    return this.processorClasses.map((processorClass) => {
      // Returns undefined
      return MetadataInspector.getClassMetadata(
        PROCESSOR_CLASS_META,
        processorClass,
      );
    })
  }
}
  

undefined Появляется только тогда, когда я вводю массив привязок с помощью декоратора @inject.tag().
Когда я вводю только один из классов, я получаю ожидаемый результат:

 export class consumerService {
  constructor(
    @inject('services.MyService')
    private readonly myService: MyService,
  )
  
  // Returns 'some_value' as expected.
  public getMetaData() {
      return MetadataInspector.getClassMetadata(
        PROCESSOR_CLASS_META,
        this.myService,
      );
  }
}
  

Ответ №1:

Декоратор @inject.tag() вводит экземпляры службы, а не классы. Вы можете получить доступ к классу (функции конструктора) через .constructor свойство.

Вот исправленная версия вашей ConsumerService реализации:

 class ConsumerService {
  constructor(
    @inject.tag('processor')
    private readonly processors: object[],
  ) {
    console.log('processors', this.processors);
    for (const proc of this.processors) {
      console.log(
        it.constructor.name,
        MetadataInspector.getClassMetadata(
          PROCESSOR_CLASS_META,
          proc.constructor,
        ),
      );
    }
  }
}
  

Когда я запускаю его с использованием ваших примеров процессоров, я получаю следующий вывод:

 processors [ MyService {}, AnotherService {} ]
MyService some_value
AnotherService another_value