2016-03-20 2 views
1

Я читал Angular 2.0 docs около инверсия зависимостей, и я также искал некоторые цифры online examples.Угловой 2.0 DI Могу ли я зависеть от абстракций?

Я понимаю, что декоратор @injectable использует компилятор TypeScript с флагом emitDecoratorMetadata для создания метаданных, которые используются для разрешения зависимостей. Возьмем, например, следующий класс:

enter image description here

машинописи компилятор использует emitDecoratorMetadata объявить с помощью метаданных, что DataService класс имеет конструктор аргумент с типом Http.

После того, как мы объявили зависимости от класса, используя @Injectable мы можем указать, что он должен быть введен в некоторые компоненты, используя Provides опцию в @App или @Component декораторов.

enter image description here

Я знаю о поведении emitDecoratorMetadata, и я знаю, что он не может испускать метаданные для интерфейсов. Поэтому, я полагаю, что я не могу зависеть от IHttp вместо Http:

enter image description here

Является ли мое предположение верно? Могу ли я зависеть от “Depend upon Abstractions. Do not depend upon concretions.” или это то, что невозможно в данный момент? Я предполагаю, что это будет исправлено, как только emitDecoratorMetadata станет способным сериализовать интерфейсы.

ответ

3

В настоящее время вам нужен тип, имя строки или OpaqueToken в качестве ключа для поставщиков.
Интерфейсы не поддерживаются, так как информация не доступна во время выполнения. Если это будет добавлено, я уверен, что DI поддержит их (он уже поддерживается в Dart).

+0

Если я использую строку, как и где я сопоставляю строку с фактическим типом? –

+3

Вместо того, чтобы просто добавлять тип к провайдерам в 'bootstrap()' или компонентах, используйте 'обеспечивать ('someName', {useClass: Http}]) и в конструкторе' @Inject ('someName') http: IHttp' –

1

Если вы используете TypeScript, у меня есть решение для вас.

Я не использую Angular 2.0, но мы разработали аналогичную библиотеку DI (intakejs). Проблема состоит в том, что TS-компилятор выделяет метаданные отражения только для классов, а не для интерфейсов (они рассматриваются как «объект»).

Надеюсь, они добавили бы такую ​​функциональность дальше, но теперь мы используем взломать на основе функции Type12 declaration merging. Идея заключается в том, что вы можете объявить интерфейс, и объединить его шпагатом или какой-либо другой среды выполнения ид, как это:

export interface IMyInjectable { 
    foo(): string; 
} 
export const IMyInjectable = 'MyInjectable'; 

Давайте предположим, что у вас есть реализация этого интерфейса:

@Injectable('MyInjectable') 
class MyInjectable implements IMyInjectable { 
    foo(): string { return 'hello' } 
} 

Тогда вы можете положиться на абстракция в вашем потребительском классе:

class MyConsumer { 

    @Inject(IMyInjectable) 
    private myInjectable: IMyInjectable; 

} 

Надеюсь, этот маленький трюк решит вашу проблему.

+0

Выглядит интересно. Декодер 'Injectable' не поддерживает такие параметры, как' @Injectable ('MyInjectable') 'хотя https://github.com/angular/angular/blob/758efba34bb347991991e780ed31130e642e65ab/modules/angular2/src/core/di/decorators.dart # L23. Это необходимо? –

+0

Как я уже говорил, я никогда не использовал Angular DI. Но я мог предположить, что '@ Injectable' создает идентификатор времени выполнения с именем класса, поэтому вы можете попробовать объединить свой интерфейс с этим именем. – koroandr

+0

Хорошо, спасибо за ваши мысли :) –

Смежные вопросы