最近,Angular 进行了迁移,用
inject
函数替换基于构造函数的注入:在大多数情况下,它很简单并且明显有好处:
// before
@Injectable({ providedIn: 'root' })
export class SomeSearchService {
constructor(
@Inject(SEARCH_DUE_TIME)
private readonly dueTime: number,
private readonly repositoryService: SomeRepositoryService
) {}
// after
@Injectable({ providedIn: 'root' })
export class SomeSearchService {
private readonly dueTime = inject(SEARCH_DUE_TIME);
private readonly repositoryService= inject(SomeRepositoryService);
但是,
inject
函数可以涵盖所有基于构造函数的注入用法吗?useFactory
?
为了说明这一点,我有:
// print.service.ts
@Injectable()
export class PrintService implements IPrintService {
constructor(
@Inject(DATA_SERVICE)
private readonly dataService: IDataService,
private readonly logger: LoggingService,
...
) {}
// tokens.ts
export const DATA_SERVICE = new InjectionToken<IDataService>('DATA_SERVICE');
export const FOO_PRINT_SERVICE = new InjectionToken<IPrintService>('FOO_PRINT_SERVICE');
export const BAR_PRINT_SERVICE = new InjectionToken<IPrintService>('BAR_PRINT_SERVICE');
// app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{
provide: FOO_PRINT_SERVICE,
useFactory: (dataService: IDataService, logger: LoggingService) => new PrintService(dataService, logger),
deps: [FOO_DATA_SERVICE, LoggingService],
},
{
provide: BAR_PRINT_SERVICE ,
useFactory: (dataService: IDataService, logger: LoggingService) => new PrintService(dataService, logger),
deps: [BAR_DATA_SERVICE, LoggingService],
},
...,
],
};
有没有办法同时使用
inject
和useFactory
constructor
中的 PrintService
声明?
是的,我们可以互换使用它们。
我们有像
skipSelf
、Optional
、Self
、Host
这样的注入装饰器,它们可以作为包含这些属性的对象的第二个参数提供。
fooPrintService = inject(FOO_PRINT_SERVICE, {
host: false,
optional: false,
self: false,
skipSelf: false,
});
从你的问题角度来看,你需要做的就是将注入令牌传递给
inject
方法,它可以在DI中检测到它。
import { Component, InjectionToken, Injectable, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
export class PrintService {
constructor(public arg: string) {}
}
@Component({
selector: 'app-root',
standalone: true,
template: `
{{fooPrintService.arg}} | {{barPrintService.arg}}
`,
})
export class App {
fooPrintService = inject(FOO_PRINT_SERVICE, {
host: false,
optional: false,
self: false,
skipSelf: false,
});
barPrintService = inject(BAR_PRINT_SERVICE);
name = 'Angular';
}
export const DATA_SERVICE = new InjectionToken<any>('DATA_SERVICE');
export const FOO_PRINT_SERVICE = new InjectionToken<any>('FOO_PRINT_SERVICE');
export const BAR_PRINT_SERVICE = new InjectionToken<any>('BAR_PRINT_SERVICE');
bootstrapApplication(App, {
providers: [
{
provide: FOO_PRINT_SERVICE,
useFactory: () => new PrintService('foo'),
},
{
provide: BAR_PRINT_SERVICE,
useFactory: () => new PrintService('bar'),
},
],
});