Angular 2.0 DI могу ли я зависеть от абстракций?

Я читал документы по Angular 2.0 о инверсия зависимостей, и я также просмотрел некоторые онлайн-примеры.

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

введите здесь описание изображения

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

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

введите здесь описание изображения

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

введите здесь описание изображения

Верно ли мое предположение? Могу ли я зависеть от "Зависеть от абстракций. Не полагайтесь на конкреции». или это что-то, что в данный момент невозможно? Я предполагаю, что это будет исправлено, как только emitDecoratorMetadata станет способным сериализовать интерфейсы.


person Remo H. Jansen    schedule 20.03.2016    source источник


Ответы (2)


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

person Günter Zöchbauer    schedule 20.03.2016
comment
Если я использую строку, как и где я могу сопоставить строку с фактическим типом? - person Remo H. Jansen; 20.03.2016
comment
Вместо того, чтобы просто добавлять тип к провайдерам в bootstrap() или компонентах, используйте provide('someName', {useClass: Http}]) и в конструкторе @Inject('someName') http:IHttp - person Günter Zöchbauer; 20.03.2016

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

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

Будем надеяться, что они добавят такую ​​​​функциональность и дальше, но сейчас мы используем хак, основанный на TypeScript слияние объявлений. Идея состоит в том, что вы можете объявить интерфейс и объединить его со строкой или другим идентификатором времени выполнения, например:

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;

}

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

person koroandr    schedule 21.03.2016
comment
Выглядит интересно. Декоратор Injectable не поддерживает такие параметры, как @Injectable('MyInjectable'), хотя github.com/angular/angular/blob/. Это необходимо? - person Günter Zöchbauer; 21.03.2016
comment
Как я упоминал ранее, я никогда не использовал Angular DI. Но я мог бы предположить, что @Injectable создает идентификатор времени выполнения с именем класса, поэтому вы можете попробовать объединить свой интерфейс с этим именем. - person koroandr; 21.03.2016