我有一个我编写的导入模块,它提供了一个带有可选依赖项的服务。事实上它恰好是可选的并不重要。这只是意味着我的应用程序没有出现错误。例如:
import { FooModule } from './foo.module';
import { BarService } from './bar.service';
// other imports and logic omitted...
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
FooModule.forRoot(options),
],
providers: [
BarService,
],
bootstrap: [AppComponent],
})
export class AppModule { }
在上面的代码中,FooModule
提供了FooService
,我可以在我的应用中使用其他地方。 FooService
具有可选的依赖关系:
export interface IBarService {
bar: (x: string) => string;
}
export const BarService = new InjectionToken<IBarService>('any compatible bar service provider');
@Injectable()
export class FooService {
constructor(
@Optional() @Inject(BarService) private barService?: IBarService,
) {
console.log(barService)
}
}
我实际上在我的第一个代码块中提供了可选的依赖项(BarService
)。然而,我发现它没有进入FooService
内的FooModule
。
它们都具有相同的注射名称:BarService
。
然而,当我运行应用程序时,控制台会将barService
记录为null
。
答案 0 :(得分:0)
当我写这个问题时,我记得提供者的useExisting
属性。我必须导入令牌(使用不同的变量名称),然后分配提供者。
import { FooModule, BarService as BarServiceForFoo } from './foo.module';
import { BarService } from './bar.service';
// other imports and logic omitted...
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
FooModule.forRoot(options),
],
providers: [
BarService,
{ provide: BarServiceForFoo, useExisting: BarService }
],
bootstrap: [AppComponent],
})
export class AppModule { }
答案 1 :(得分:0)
它们都具有相同的注射名称:BarService
这一部分具有误导性,因为InjectionToken
名称与调试无关。
此时它们是不同的令牌,除了开发人员的意图之外没有任何共同之处。 useExisting
是一个选项,但它需要父项和所有其他模块依赖于BarService
或者实现它依赖于Foo模块。
一个可能的解决方案是使用字符串标记,它很容易被反模式化,因为它提供了松散耦合和全局命名空间(这就是引入标记类的原因)但它符合当前的情况:
...
{ provide: 'vendorNamespace.BarService', useExisting: BarService }
...
...
constructor(
@Optional() @Inject('appNamespace.BarService') private barService?: IBarService
) {}
...
另一个解决方案是使公共模块包含提供者令牌和接口......这是抽象类:
export abstract class BarService {
abstract bar(x: string): string;
}
import { BarService as AbstractBarService } from 'common';
export class BarService implements AbstractBarService { ... }
import { BarService as AbstractBarService } from 'common';
import { BarService } from './bar.service';
...
{ provide: AbstractBarService, useClass: BarService }
...
这自然允许为提供者注入类型注释:
import { BarService } from 'common';
...
constructor(
@Optional() private barService?: BarService
) {}
...