Добавить поставщиков после объявления AppModule

Angular 2+ регистрирует провайдеров следующим образом:

// @NgModule decorator with its metadata
@NgModule({
  declarations: [...],
  imports: [...],
  providers: [<PROVIDERS GO HERE>],
  bootstrap: [...]
})
export class AppModule { }

Я хочу зарегистрировать провайдеров на уровне приложения отдельно от этого сайта объявлений.

В частности, я использую NSwag для создания клиентов службы для всего моего веб-API и хочу динамически добавлять их всех в качестве поставщиков. Однако я не уверен, как это сделать, поскольку @NgModule — это атрибут, применяемый к этому классу AppModule.

Это возможно?


person MgSam    schedule 06.02.2018    source источник
comment
Это помогает? damirscorner.com/blog/posts/   -  person David    schedule 06.02.2018


Ответы (1)


Любой поставщик DI должен быть включен в модуль во время компиляции.

Поскольку внедрение зависимостей Angular работает с символами/токенами типа Typescript, нет функциональности Javascript для выполнения той же задачи после ее компиляции.

Что вы можете сделать, так это динамически добавить поставщика во время компиляции, например:

import { Load, SomeToken } from '../someplace';


@NgModule({
  declarations: [...],
  imports: [...],
  providers: [
    {
      provide: SomeToken,
      useValue: Load(someVariable)
  ],
  bootstrap: [...]
})
export class AppModule { }

а затем реализовать функцию Load и токен в другом месте:

export const SomeToken = new OpaqueToken<any>('SomeToken');

export const Load = (someVariable) => {
  // logic to return an @Injectable here. Variable provided could be something like an environment variable, but it has to be exported and static
}

Этот подход, конечно, имеет ограничение, заключающееся в том, что его нужно знать во время компиляции. Другой подход заключается в глобальном импорте всех провайдеров, которые необходимы во всем приложении, независимо от обстоятельств, а затем в ленивой загрузке компонентов, в которых есть соответствующий провайдер, введенный для этого обстоятельства (Angular не будет инициализировать провайдера до тех пор, пока компонент, который его использует, не будет инициализирован), или создать поставщика, который сам по себе способен выполнять логику независимо от динамических критериев. Идея состоит в том, чтобы создать еще один сервис, который использует этот сервис и решает проблемы на основе этих динамических критериев (т. е. у вас может быть метод с именем GetLoginInfo в первом сервисе, а второй сервис сможет разрешить правильный вызов API для этого метода.)

Если вам нужна только информация API (т. е. URL-адреса), то вы могли бы добиться вышеуказанного, захватив информацию URL-адреса из файла config.json или вызова API и внедрив эти значения в службу, чтобы вызовы и токены оставались прежними, но использовать разные значения. Подробнее о том, как это сделать, см. здесь.

person joh04667    schedule 06.02.2018
comment
В приведенном выше коде вам по-прежнему нужен отдельный объект провайдера для каждого провайдера? Моя цель здесь состояла в том, чтобы автоматизировать создание и регистрацию службы Angular всякий раз, когда добавляется новый веб-API, поэтому количество поставщиков не должно быть известно на сайте объявления. - person MgSam; 06.02.2018
comment
Да, вам понадобится отдельный оформленный провайдер. Поставщики должны быть оформлены и внедрены во время выполнения. - person joh04667; 06.02.2018
comment
Должны ли провайдеры быть другим кодом или просто разными экземплярами одного и того же провайдера? - person joh04667; 06.02.2018
comment
Каждый провайдер — это отдельный класс. - person MgSam; 07.02.2018