NodeJS 有没有办法在NestJS中使用静态方法和依赖注入?

cotxawn7  于 2023-08-04  发布在  Node.js
关注(0)|答案(4)|浏览(98)

一个例子比一个冗长的解释更好:

// Backery.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Backery } from './Backery.entity';

@Injectable()
export class BackeryService {
  constructor(
    @InjectRepository(Backery)
    private readonly backeryRepository: Repository<Backery>,
  ) {}

  static myStaticMethodToGetPrice() {
    return 1;
  }

  otherMethod() {
    this.backeryRepository.find();
    /* ... */
  }
}

个字符
我怎样才能替换BakeryService.myStaticMethodToGetPrice()来使用依赖注入,这样我就可以很容易地进行测试了?

edqdpe6u

edqdpe6u1#

静态方法不能使用依赖注入。这是因为依赖注入的想法(至少对Nest来说)是注入依赖的示例,以便以后可以利用它们。
您拥有的代码是有效的,因为它将返回值1,就像静态方法说的那样,但是静态方法不能使用任何注入的示例值。您会发现这种逻辑在大多数其他DI框架中都遵循。

de90aj5v

de90aj5v2#

有一种非常简单的方法可以创建使用NestJs DI中的服务的静态函数。
一个很好的例子是使用域事件和避免使用技术服务污染实体的构造函数。
在你的主.ts

let app: INestApplication;

async function bootstrap() {
  app = await NestFactory.create(AppModule);

  install();
  ...
  ...
}

bootstrap();

export const getInstance = () => {
  return app;
};

字符串
从应用内的任何静态上下文:

import { getInstance } from '@/main';

static async emmitEvent() {
    let eventEmitter = await getInstance().resolve(EventEmitter2);
    eventEmitter.emit(JSON.stringify(nodeCreateEvent));
}

1cklez4t

1cklez4t3#

我用静态属性和@Inject()解决了这个问题

import { GeoService } from '../geoservice/geoservice.service';
import { Inject } from '@nestjs/common';

export class myClass {
    @Inject(GeoService)
    private static geoService: GeoService;

    someMethod() {
        this.geoService...
    }
}

字符串

x0fgdtte

x0fgdtte4#

我是这样做的:

// app-context.ts
import { INestApplication, Type } from '@nestjs/common';

export class AppContext {
  static instance: INestApplication;

  // eslint-disable-next-line @typescript-eslint/ban-types
  static tryGet<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol): TResult | null {
    if (!AppContext.instance) return null;
    try {
      return AppContext.instance.get(typeOrToken);
    } catch (err) {
      return null;
    }
  }
}

字符串
在main.ts中:

const app = AppContext.instance = await NestFactory.create(AppModule, {
  // ...
});


那么你需要这些装饰器:

// decorators.ts
export const DEPENDENCY_INJECTION_METADATA = 'self:dependency_injection';

export function StaticInject<T>(type: T): ParameterDecorator {
  return (target: object, _key: string | symbol | undefined, index: number) => {
    let dependencies = Reflect.getMetadata(DEPENDENCY_INJECTION_METADATA, target) || [];
    dependencies = [...dependencies, { index, key, type }];
    Reflect.defineMetadata(DEPENDENCY_INJECTION_METADATA, dependencies, target);
  };
}

export const StaticInjection: MethodDecorator = (target: object, key: string | symbol, descriptor: PropertyDescriptor) => {
  const dependencies = Reflect.getMetadata(DEPENDENCY_INJECTION_METADATA, target) || [];
  const originalMethod = descriptor.value;
  descriptor.value = function(...args: unknown[]) { // do to use arrow function here! we need to keep function context
    if (!AppContext.instance) throw new Error('AppContext is not initialized');
    for (const { index, type } of dependencies) {
      args[index] = AppContext.tryGet(type);
      if (!args[index]) throw new Error(`Dependency injection failed for ${type}`);
    }
    return originalMethod.apply(this, args);
  };
};


最后,在静态方法中:

@StaticInjection
  static myMethod(otherParams: any, @StaticInject(SomeService) someService?: SomeService) {
    return someService.something(otherParams);
  }

相关问题