Interface 可以用angular2注入接口吗?
我想知道是否有合适的方法在Angular2中注入接口?(参见下文) 我认为这与接口上缺少@Injectable()装饰符有关,但这似乎是不允许的 问候 当CourseServiceInterface作为接口实现时,TypeScript编译器会抱怨“CourseServiceInterface找不到名称”: 但是使用CourseServiceInterface作为接口:Interface 可以用angular2注入接口吗?,interface,angular,inject,Interface,Angular,Inject,我想知道是否有合适的方法在Angular2中注入接口?(参见下文) 我认为这与接口上缺少@Injectable()装饰符有关,但这似乎是不允许的 问候 当CourseServiceInterface作为接口实现时,TypeScript编译器会抱怨“CourseServiceInterface找不到名称”: 但是使用CourseServiceInterface作为接口: import {Injectable} from 'angular2/core'; import {Course} from '
import {Injectable} from 'angular2/core';
import {Course} from './Course.class';
//@Injectable()
export interface CoursesServiceInterface {
getAllCourses(): Promise<Course[]>;//{ return null; };
getCourse(id: number): Promise<Course>;// { return null; };
remove(id: number): Promise<{}>;// { return null; };
}
从'angular2/core'导入{Injectable};
从“./Course.class”导入{Course};
//@可注射()
导出接口CourseServiceInterface{
getAllCourses():Promise;//{return null;};
getCourse(id:number):Promise;//{returnnull;};
remove(id:number):Promise;//{returnnull;};
}
当服务是一个类时,TypeScript编译器不再抱怨:
import {Injectable} from 'angular2/core';
import {Course} from './Course.class';
@Injectable()
export class CoursesServiceInterface {
getAllCourses() : Promise<Course[]> { return null; };
getCourse(id: number) :Promise<Course> { return null; };
remove (id: number) : Promise<{}> { return null; };
}
从'angular2/core'导入{Injectable};
从“./Course.class”导入{Course};
@可注射()
导出类CourseServiceInterface{
getAllCourses():承诺{returnnull;};
getCourse(id:number):承诺{returnnull;};
remove(id:number):承诺{returnnull;};
}
否,DI不支持接口。使用TypeScript时,接口在运行时不再可用,只能静态使用,因此不能用作DI令牌
或者,您可以使用字符串作为键或InjectionToken
provide('CourseServiceInterface',{useClass:CourseServiceMock})//old
提供者:[{provide:'CourseServiceInterface',useClass:CourseServiceMock}]
然后像注射一样注射
构造函数(@Inject('CourseServiceInterface')私有CourseService:CourseServiceInterface){
另请参见使用OpaqueToken,DI不支持接口,因为Javascript本身没有接口。在Angular 2中执行此操作的一种方法是使用OpaqueToken。 我希望这能有所帮助。我对前端开发的经验(来自java后端开发)如下 如果我们谈论“接口”,我强烈期望“提供”接口的语言能够保证使用接口的主要原则。 这就是:“针对接口而不是实现的代码” typescript/angular2似乎无法保证这一点。(也许他们还不应该使用word界面) 我的情况是什么(警告:我正在学习angular2,所以我的解决方案对高级用户来说可能很难看):
组件A1有一个子组件B。
组件B应该知道父级并调用父级上的方法。
因此组件B通过其构造函数中的DependencyInjection接收父级
constructor( private a: A1Component) {}
一切都很好事情变得复杂了
另一个组件A2可以是comp的父组件。B.
理想情况下,我应该在B中注入一个由A1和A2实现的接口(而不是实现)(这在java世界中是很自然的)。
B将使用此接口。如果需要,例如,将typecast转换为A2将使B知道他拥有的实例是否真的是A2 我说的是普通组件/类,而不是服务(我看到大多数解决方案都是指服务)。
我尝试使用@Host()、@Injectable()、OpaqueToken和Providers,但总是出现错误。最后,它似乎起了作用:实际上,组件B中注入的对象是一个空对象,而不是父对象-可能我错误地使用了提供者,并创建了一个新的空对象,而不是注入父对象 我最后做了什么:我没有使用界面。
我为A1和A2创建了一个简单的基类——我们称之为ABase。
组件B将保留对此基类的引用。引用将在构造函数中设置为:
//BComponent:
parent: ABase;
constructor(@Optional parentA1: A1Component, @Optional parentA2: A2Component) {
if( parentA1 )
this.parent = parentA1;
else
this.parent = parentA2
}
是的,这是一个奇怪的解决方法,不太好(来自java世界的思考,我同意)——但我只是没时间了,对“接口”的事情感到失望
更新
我重新考虑了之前的答案(它的设计很糟糕,很难看…在我刚开始使用angular时)
现在Angular的文档已经清楚地描述了这个问题:查找组件的父级
无法使用接口-因为无法注入接口
“寻找实现接口的组件会更好。这是不可能的,因为TypeScript接口会从不支持接口的传输JavaScript中消失。没有可查找的工件。”
两者都不能用。。。(这是我之前绝望、糟糕回答的根本原因)
什么有效?技术:
主要是:
子B查看一般父级父级(可以是a1组件或a2组件)
每个可能的父组件都提供一个父组件(在组件级别!!!),使用:
不能使用接口的原因是接口是TypeScript设计时工件。JavaScript没有接口。TypeScript接口从生成的JavaScript中消失。运行时,Angular无法找到任何接口类型信息
解决方案1:
最简单的解决方案就是定义一个实现接口的抽象类。通常,您需要一个抽象类
接口:
import {Role} from "../../model/role";
export interface ProcessEngine {
login(username: string, password: string):string;
getRoles(): Role[];
}
抽象类:
import {ProcessEngine} from "./process-engine.interface";
export abstract class ProcessEngineService implements ProcessEngine {
abstract login(username: string, password: string): string;
abstract getRoles(): Role[];
}
混凝土等级:
import { Injectable } from '@angular/core';
import {ProcessEngineService} from "./process-engine.service";
@Injectable()
export class WebRatioEngineService extends ProcessEngineService {
login(username: string, password: string) : string {...}
getRoles(): Role[] {...}
}
现在,您可以像往常一样定义提供商:
@NgModule({
...
providers: [
...,
{provide: ProcessEngineService, useClass: WebRatioEngineService}
]
})
解决方案2:
Angular的官方文档建议使用,类似于OpaqueToken。以下是一个例子:
您的接口和类:
export interface AppConfig {
apiEndpoint: string;
title: string;
}
export const HERO_DI_CONFIG: AppConfig = {
apiEndpoint: 'api.heroes.com',
title: 'Dependency Injection'
};
定义您的令牌:
import { InjectionToken } from '@angular/core';
export let APP_CONFIG = new InjectionToken<AppConfig>('app.config');
然后,在@inject decorator的帮助下,您可以将配置对象注入到任何需要它的构造函数中:
constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title;
}
角9的替代解决方案
@Injectable()
export class TodoListPublicService implements TodoListService {
getTodos(): Todo[] {
const todos: Todo[] = [
{
title: 'get groceries',
description: 'eggs, milk, etc.',
done: false
}
];
return todos;
}
}
创建一个抽象类
export interface Todo {
title: string;
description: string;
done: boolean;
}
@Injectable()
export abstract class TodoListService {
abstract getTodos(): Todo[];
}
在组件中使用
providers: [
{ provide: TodoListService, useClass: TodoListPublicService }
]
export class TodoListComponent implements OnInit {
todos: Todo[];
constructor(private todoListService: TodoListService) { }
ngOnInit() {
}
对于那些以Angular 4为目标并找到了这个答案的人来说,解决方案2无疑是一条路要走。通过这种设置,可以为单元te注入任何类型的模拟类
providers: [{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }]
constructor(@Inject(APP_CONFIG) config: AppConfig) {
this.title = config.title;
}
@Injectable()
export class TodoListPublicService implements TodoListService {
getTodos(): Todo[] {
const todos: Todo[] = [
{
title: 'get groceries',
description: 'eggs, milk, etc.',
done: false
}
];
return todos;
}
}
export interface Todo {
title: string;
description: string;
done: boolean;
}
@Injectable()
export abstract class TodoListService {
abstract getTodos(): Todo[];
}
providers: [
{ provide: TodoListService, useClass: TodoListPublicService }
]
export class TodoListComponent implements OnInit {
todos: Todo[];
constructor(private todoListService: TodoListService) { }
ngOnInit() {
}