Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection 注入vs可注入vs自定义提供程序_Dependency Injection_Nestjs - Fatal编程技术网

Dependency injection 注入vs可注入vs自定义提供程序

Dependency injection 注入vs可注入vs自定义提供程序,dependency-injection,nestjs,Dependency Injection,Nestjs,我很难弄清楚什么时候该用什么。我了解DI,并且已经做了很多年了,但是在NestJS中,文档中似乎缺少了一些东西,这有助于我理解为什么注入项中缺少一些指定属性 我们有一个通过自定义提供程序注入的记录器 通过查看文档,他们会在构造函数区域添加@Inject,但是如果我是通过自定义提供程序进行注入,为什么要使用@Inject 同样,如果我们有自定义提供程序处理模块的所有注入设置,为什么要使用@Injectable 出现的问题是,文件名在其他注入服务中丢失,有时当记录器在一个服务中执行时,文件名是相同的

我很难弄清楚什么时候该用什么。我了解DI,并且已经做了很多年了,但是在NestJS中,文档中似乎缺少了一些东西,这有助于我理解为什么注入项中缺少一些指定属性

我们有一个通过自定义提供程序注入的记录器

通过查看文档,他们会在构造函数区域添加
@Inject
,但是如果我是通过自定义提供程序进行注入,为什么要使用
@Inject

同样,如果我们有自定义提供程序处理模块的所有注入设置,为什么要使用
@Injectable

出现的问题是,文件名在其他注入服务中丢失,有时当记录器在一个服务中执行时,文件名是相同的,而在其他时间,服务不同,它将保留来自不同服务的ctor名称的文件名

不管怎么说,我不明白为什么要用一套来代替另一套

更新:我发现我们在某些服务上遵循生命周期,但我发现记录器在执行时没有保留

//custom-provider
export ClientProvider = {
   provide: Client,
   userFactory: (logger: Logger): Client => {
        return new Client(logger);
   },
   inject: [Logger.getToken()]
};

//client
export class Client{
    private readonly logger;
    constructor(logger:Logger){
        this.logger = logger;
        if (this.logger) this.logger.fileName = this.constructor.name;
    }
}

//logger
export class Logger {
    static getToken(): string { return 'the-token-key'; }
    private filename: string;

    constructor(filename: string){
        this.filename = filename;
    }
}

//cat-service
export class CatService implements OnModuleInit {
    private readonly logger;
    constructor(@Inject(Logger.getToken()) private logger:Logger){
        this.logger = logger;
    }

    onModuleInit() {
       if (this.logger) this.logger.fileName = this.constructor.name;
    }
}


所以,在高层,Nest自然地使用从Typescript反射的元数据来知道绑定什么和绑定到哪里。通常,这种元数据类似于运行时存在的类名,这就是为什么不能使用接口

@Injectable()
告诉Nest它应该查找此类构造函数中提供的元数据,并找到正确的提供程序。正如前面提到的,这就是Nest执行大部分DI的方式

@Inject()
告诉Nest,“嘿,我知道这说明它是一个
记录器
类,但实际上是用我告诉您的注入令牌向提供者注入”,这对于使用记录器类的特定实例等非常有用

对于自定义提供程序,
@Injectable()
在您使用工厂时是不必要的,如您所示,但如果您使用类来代替,则是必要的,因为工厂返回要提供的值的实例,而对于
useClass
,您返回的是Nest需要实例化的类定义


我能看到您的文件名被覆盖的唯一原因是,提供程序是模块之间的单例作用域,但是如果同一个提供程序在
提供程序
数组中,那么每次都应该是一个新实例,所以可能有点不稳定谢谢@Jay!我想得更多了,我忘了单身汉。另外,谢谢你的解释,它真的帮助了我。让我问你:令牌只是命名配置吗?例如,如果您有多个相同类的设置,令牌可以帮助您保持唯一性以供注入?这绝对是一个很好的方法。对于我目前正在构建的系统,我有一个自定义装饰器,可以接受参数。这个decorator本质上是嵌套的
@Inject()
decorator的包装器,它有助于创建正确的注入令牌。此令牌由decorator和动态模块的
forFeature()
函数创建,以确保为当前上下文正确创建提供程序令牌。