在NestJS中有一种场景,在注入的时候需要将多个实现了同一个接口的service都注入到系统里,而NestJS中默认时没有这种注入,此时我们可以使用一个变通的provider来实现这一功能。
看下面例子,假定我们有一个OSService接口,其中定义了一个方法返回OSUser数组,假定我们有多个实现类,比如这里的LinuxOSService和WindowsOSService,我们希望将这两个实现类都注入到系统中,那么我们可以这样实现:
osuser.ts
定义一下基本的OSUser对象和OSUserType枚举。
export interface OSUser {
name: string;
type: OSUserType;
}
export enum OSUserType {
LINUX = 'LINUX',
WINDOWS = 'WINDOS',
}
osuser.service.ts
定义OSUserService接口和两个实现类LinuxOSUserService和WindowsOSUserService。
import { Injectable } from '@nestjs/common';
import { OSUser, OSUserType } from './osuser';
export interface OSUserService {
getUsers(): OSUser[];
}
@Injectable()
export class LinuxOSUserService implements OSUserService {
users: OSUser[] = [];
getUsers(): OSUser[] {
this.users = [
{ name: 'John', type: OSUserType.LINUX },
{ name: 'Jane', type: OSUserType.LINUX },
{ name: 'Bob', type: OSUserType.LINUX },
];
return this.users;
}
}
@Injectable()
export class WindowsOSUserService implements OSUserService {
users: OSUser[] = [];
getUsers(): OSUser[] {
this.users = [
{ name: 'John', type: OSUserType.WINDOWS },
{ name: 'Jane', type: OSUserType.WINDOWS },
{ name: 'Bob', type: OSUserType.WINDOWS },
];
return this.users;
}
}
osuser.controller.ts
控制器注入了OSUserServices,这是一个数组,包含了所有的OSUserService实现类,然后在list方法中遍历这个数组,获取所有的OSUser对象,最后返回。
import { Controller, Get, Param, Inject } from '@nestjs/common';
import { OSUserService } from './osuser.service';
import { OSUser, OSUserType } from './osuser';
@Controller('osuser')
export class OSUserController {
constructor(
@Inject('OSUserServices') private osUserServices: OSUserService[],
) {}
@Get()
list() {
const osUsers: OSUser[] = [];
this.osUserServices.map((osUserService) => {
osUserService.getUsers().map((osUser) => osUsers.push(osUser));
});
return osUsers;
}
}
osuser.module.ts
模块的providers中定义了两个OSUserService的实现类,并且定义了一个新的provider,这个provider的名字是'OSUserServices',它的值是一个工厂函数,这个工厂函数接收两个参数,分别是LinuxOSUserService和WindowsOSUserService,然后返回一个数组,这个数组包含了所有的OSUserService实现类。
import { Module } from '@nestjs/common';
import { OSUserController } from './osuser.controller';
import {
OSUserService,
LinuxOSUserService,
WindowsOSUserService,
} from './osuser.service';
@Module({
imports: [],
controllers: [OSUserController],
providers: [
LinuxOSUserService,
WindowsOSUserService,
{
provide: 'OSUserServices',
useFactory: (linuxOSUserService, windowsOSUserService) => [
linuxOSUserService,
windowsOSUserService,
],
inject: [LinuxOSUserService, WindowsOSUserService],
},
],
})
export class OSUserModule {}
总结
通过以上步骤,我们实现了在NestJS中注入多个实现了同一个接口的service的功能,这种变通的方法可以解决一些特殊场景下的注入问题。