【发布时间】:2021-12-17 13:51:58
【问题描述】:
假设我们有 SomeService 接受 Iprovider 作为它的依赖项,我希望能够根据哪个控制器调用 SomeService 为 Iprovider 使用不同的实现。这在 Nestjs 中是如何实现的?
【问题讨论】:
标签: dependency-injection dependencies nestjs code-injection
假设我们有 SomeService 接受 Iprovider 作为它的依赖项,我希望能够根据哪个控制器调用 SomeService 为 Iprovider 使用不同的实现。这在 Nestjs 中是如何实现的?
【问题讨论】:
标签: dependency-injection dependencies nestjs code-injection
您可以使用Injection Token
这是一个示例代码:
此示例假定您已经设置了一个 NestJS 项目。这是一个简单的表格。显然,现实世界的实现可能会或可能不会不同
提供者接口
export interface IProvider{
method();
}
实现
实施 1
import {IProvider} from '<path>';
//This token will be used to inject ProviderOne instance
export const ProviderOneToken = 'provider_one';
export class ProviderOne implements IProvider{
public method(){
console.log('ProviderOne');
}
}
实施 2
import {IProvider} from '<path>';
//This token will be used to inject ProviderTwo instance
export const ProviderTwoToken = 'provider_two';
export class ProviderTwo implements IProvider{
public method(){
console.log('ProviderTwo');
}
}
现在在App module,
//Imports....
@Module({
providers:[
{provide:ProviderOneToken, useClass:ProviderOne},
{provide:ProviderTwoToken, useClass:ProviderTwo},
// The service we are going to test the token based
// injection
ServiceToInject
]
})
export class AppModule{
}
ServiceToInject
import {Injectable,Inject} from '@nestjs/common'
//Imports....
@Injectable()
export class ServiceToInject{
constructor(@Inject(ProviderOneToken) private readonly provider:IProvider){
}
public serviceMethod(){
//Calls method of ProviderOne instance(service)
// Logs = 'ProviderOne'
this.provider.method();
}
}
现在换掉令牌,
import {Injectable,Inject} from '@nestjs/common'
//Imports....
@Injectable()
export class ServiceToInject{
// Changed provider token inside @Inject(<Here>).Rest are same
constructor(@Inject(ProviderTwoToken) private readonly provider:IProvider){
}
public serviceMethod(){
//Calls method of ProviderTwo instance(service)
// Logs = 'ProviderTwo'
this.provider.method();
}
}
同一服务中的两个令牌:
import {Injectable,Inject} from '@nestjs/common'
//Imports....
@Injectable()
export class ServiceToInject{
constructor(@Inject(ProviderTwoToken) private readonly providerTwo:IProvider,
@Inject(ProviderOneToken) private readonly providerOne:IProvider
){
}
public serviceMethod(){
//Calls method of ProviderOne instance(service)
// Logs = 'ProviderOne'
this.providerOne.method();
//Calls method of ProviderTwo instance(service)
// Logs = 'ProviderTwo'
this.providerTwo.method();
}
}
更新:
ServiceToInject 也可以是控制器。
ControllerOne
@Controller('one')
export class ControllerOne{
constructor(@Inject(ProviderOneToken) private readonly providerOne:IProvider){}
@Get()
public getOne(){
//Logs - 'ProviderOne'
this.provider.method();
}
}
ControllerTwo
@Controller('two')
export class ControllerTwo{
constructor(@Inject(ProviderTwoToken) private readonly providerOne:IProvider){}
@Get()
public getTwo(){
//Logs - 'ProviderTwo'
this.provider.method();
}
}
【讨论】: