Можно ли вводить сервисы в сервисы только через загрузчик?
Я пытаюсь подключить основное приложение 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();
Я пока не знаю, разрешается ли это по-прежнему из "я", если родитель не может предоставить запрошенный тип.