Angular 6 服务与接口
Angular 6 service with interface
我正在使用 Angular (6.0.7
) 构建一个应用程序,我正在尝试使用新的:
创建一个服务
@Injectable({
providedIn: 'root'
})
但是如何使用接口输入注入?
问题
我有 2 个服务,Authentication.service 和 SessionStorage.service。我想将会话存储注入身份验证服务。这可以通过以下方式完成:
constructor(private sessionStorage: SessionStorage) {
}
没问题。但是出于面向对象的目的,我希望在此服务之上有一个 interface
(这样我就可以将本地存储服务实现为会话存储服务)。因此,我想用接口输入注入的 class 是合乎逻辑的,但这不能以相同的方式完成 .
那么如何使用我的界面将注入输入到这个全局服务中呢?
我试过了
Angular 服务类型描述了一个 InjectableProvider
,但这与 InjectableProvider
的兄弟姐妹的任何参数都不匹配,因此这会产生编译器(和 tslint)错误.
@Injectable({
providedIn: 'root'
}, {provide: IStorageService, useClass: SessionStorage})
你可以使用类似 -
[{ provide: InterfaceName, useClass: ClassName}]
我使用了类似下面的方法来解决这个问题
app.module.ts
providers: [
{ provide: AlmostInterface, useClass: environment.concrete }
...
]
AlmostInterface.ts
export abstract class AlmostInterface {
abstract myMethod();
}
MyConcrete.ts
export class MyConcrete implements AlmostInterface {
myMethod() { ... }; // implementation
}
export class MyConcreteAlternative implements AlmostInterface {
myMethod() { ... }; // implementation
}
environment.ts
export const environment = {
production: false,
concrete: MyConcreteAlternative
};
environment.prod.ts
export const environment = {
production: true,
concrete: MyConcrete
};
我认为你不能使用类型脚本接口进行依赖注入,因为类型脚本接口在运行时不存在(仅用于编译时的类型安全)。
我建议使用摘要class。
编辑:
看来您可以在@Injectable 的first 参数中使用useClass
,而不是像您的示例那样使用第二个参数。将其与 @k0zakinio 的答案结合起来:
@Injectable({
providedIn: 'root',
useClass: environment.concrete,
deps: []
})
export abstract class SessionStorage { }
您似乎还需要通过 deps
或 inject
声明您的依赖项,请查看此 github issue。希望这次我的回答能对您有所帮助
这可以用 InjectionToken
来完成,它替代了过时的 OpaqueToken
export const AuthenticationProvider = new InjectionToken(
"AuthenticationProvider",
{ providedIn: "root", factory: () => new CognitoAuthenticationProvider() }
);
...
@Injectable()
export class CognitoAuthenticationProvider implements IAuthenticationProvider {
...
@Injectable({
providedIn: "root"
})
export class AuthenticationService {
constructor(
@Inject(AuthenticationProvider)
private authenticationProvider: IAuthenticationProvider,
private http: HttpClient
) {}
我正在使用 Angular (6.0.7
) 构建一个应用程序,我正在尝试使用新的:
@Injectable({
providedIn: 'root'
})
但是如何使用接口输入注入?
问题
我有 2 个服务,Authentication.service 和 SessionStorage.service。我想将会话存储注入身份验证服务。这可以通过以下方式完成:
constructor(private sessionStorage: SessionStorage) {
}
没问题。但是出于面向对象的目的,我希望在此服务之上有一个 interface
(这样我就可以将本地存储服务实现为会话存储服务)。因此,我想用接口输入注入的 class 是合乎逻辑的,但这不能以相同的方式完成
那么如何使用我的界面将注入输入到这个全局服务中呢?
我试过了
Angular 服务类型描述了一个 InjectableProvider
,但这与 InjectableProvider
的兄弟姐妹的任何参数都不匹配,因此这会产生编译器(和 tslint)错误.
@Injectable({
providedIn: 'root'
}, {provide: IStorageService, useClass: SessionStorage})
你可以使用类似 -
[{ provide: InterfaceName, useClass: ClassName}]
我使用了类似下面的方法来解决这个问题
app.module.ts
providers: [
{ provide: AlmostInterface, useClass: environment.concrete }
...
]
AlmostInterface.ts
export abstract class AlmostInterface {
abstract myMethod();
}
MyConcrete.ts
export class MyConcrete implements AlmostInterface {
myMethod() { ... }; // implementation
}
export class MyConcreteAlternative implements AlmostInterface {
myMethod() { ... }; // implementation
}
environment.ts
export const environment = {
production: false,
concrete: MyConcreteAlternative
};
environment.prod.ts
export const environment = {
production: true,
concrete: MyConcrete
};
我认为你不能使用类型脚本接口进行依赖注入,因为类型脚本接口在运行时不存在(仅用于编译时的类型安全)。
我建议使用摘要class。
编辑:
看来您可以在@Injectable 的first 参数中使用useClass
,而不是像您的示例那样使用第二个参数。将其与 @k0zakinio 的答案结合起来:
@Injectable({
providedIn: 'root',
useClass: environment.concrete,
deps: []
})
export abstract class SessionStorage { }
您似乎还需要通过 deps
或 inject
声明您的依赖项,请查看此 github issue。希望这次我的回答能对您有所帮助
这可以用 InjectionToken
来完成,它替代了过时的 OpaqueToken
export const AuthenticationProvider = new InjectionToken(
"AuthenticationProvider",
{ providedIn: "root", factory: () => new CognitoAuthenticationProvider() }
);
...
@Injectable()
export class CognitoAuthenticationProvider implements IAuthenticationProvider {
...
@Injectable({
providedIn: "root"
})
export class AuthenticationService {
constructor(
@Inject(AuthenticationProvider)
private authenticationProvider: IAuthenticationProvider,
private http: HttpClient
) {}