【问题标题】:How to switch between different implementation that implements same interface as a dependency for a service in nest js如何在实现相同接口的不同实现之间切换作为嵌套js中服务的依赖项
【发布时间】:2021-12-17 13:51:58
【问题描述】:

假设我们有 SomeService 接受 Iprovider 作为它的依赖项,我希望能够根据哪个控制器调用 SomeService 为 Iprovider 使用不同的实现。这在 Nestjs 中是如何实现的?

【问题讨论】:

    标签: dependency-injection dependencies nestjs code-injection


    【解决方案1】:

    您可以使用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();
    }
     
    }
    

    【讨论】:

    • 感谢您的回答。我有另一个问题。假设提供者的实现取决于调用 ServiceToInject 类的控制器,例如,如果 controllerOne 正在调用 ServiceToInject 类,那么应该使用 ProviderOne,并且应该使用 ProviderTwo,而 ControllerTwo 调用类 ServiceToInject。我们该怎么做?
    • 解决此问题的最简单方法是将参数传递给 serviceToInject 方法,并让该方法使用 if else 处理它。在大多数情况下可能会这样做
    猜你喜欢
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多