Можно ли вводить сервисы в сервисы только через загрузчик?

Я пытаюсь подключить основное приложение Angular2, которое использует службу Http. (Большинство уроков, которые я видел, делают это, имея Component потреблять Http сервис, который кажется неправильным, если базовая философия тонких контроллеров не изменилась - но это другой вопрос.)

Я хотел бы создать сервис, который использует Angular's Http оказание услуг. Но я не могу понять, как вводить Http Сервис кроме этого:

boot.ts:

import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {HTTP_PROVIDERS } from 'angular2/http';

bootstrap(AppComponent, [HTTP_PROVIDERS]);

myService.ts:

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';

@Injectable()
export class aService{
    constructor(http:Http){
    }
    /** do some stuff *//
}

Это работает, но кажется неправильным требовать, чтобы пользователь службы знал зависимости службы и был вынужден внедрить их в процесс начальной загрузки. Кажется, должен быть способ напрямую передать providers массив для службы так же, как вы можете компонент, но я не могу его найти. Я что-то пропустил?

1 ответ

Решение

Обновить

Таким образом, если родительский инжектор обеспечивает реализацию для OtherService этот используется, в противном случае OtherServiceImpl используется (по умолчанию).

@Injectable()
class SomeService {
  OtherService _other;

  SomeService(Injector injector) {
    _other = injector.getOptional(OtherService);
    if (_other == null) {
      _other = injector.resolveAndCreateChild([
        provide(OtherService, useClass: OtherServiceImpl)
      ]).get(OtherService);
    }
    _other.doSomething();
  }
}

Если вы предоставите еще один, как

bootstrap(AppElement, [
  provide(OtherService, useClass: OtherServiceImpl2)
]);

OtherServiceImpl2 используется.

Смотрите также https://github.com/angular/angular/issues/5622

оригинал

Вы могли бы просто сделать http услуга необязательна (используя @Optional() аннотации), и если ничего не предоставлено, просто создайте экземпляр внутри конструктора с помощью new Http(), Таким образом, пользователю не нужно знать о зависимостях служб, но он может передавать альтернативные реализации при необходимости (например, для тестирования). Если для создания зависимости внутри службы требуется сам DI, вы можете добавить инжектор и использовать его для получения зависимостей. См. Также необязательные зависимости в http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html

То, что также может сработать (еще не пробовал сам) - это просто создать инжектора для детей и дать ему указание пропустить себя.

От SkipSelfMetadata документация

  class Dependency {
  }

  @Injectable()
  class NeedsDependency {
    dependency;
    constructor(@SkipSelf() dependency:Dependency) {
      this.dependency = dependency;
    }
  }

  var parent = Injector.resolveAndCreate([Dependency]);
  var child = parent.resolveAndCreateChild([NeedsDependency]);
  expect(child.get(NeedsDependency).dependency instanceof Depedency).toBe(true);

  var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
  expect(() => inj.get(NeedsDependency)).toThrowError();

Я пока не знаю, разрешается ли это по-прежнему из "я", если родитель не может предоставить запрошенный тип.

Другие вопросы по тегам