javascript - tsyringe - Injiserer en avhengighet med overbelastet konstruktør


Hei venner, hvordan har dere det?

Jeg prøver å gjøre noe annerledes, jeg vet ikke om det er bort fra selve konseptet, men det ville hjelpe meg å oppnå det jeg prøver å gjøre på en elegant måte.

Jeg bruker et repository-mønster, og i implementeringen vil jeg bruke en overbelastet konstruktør og bruke et valgfritt argument, i prinsippet sende noe tilleggsinformasjon når det trengs.

Problemet er at det fungerer bra når konstruktøren er tom, men når du endrer signaturen for å motta ett argument til, kaster TSYSRINGE en unntak.

Jeg tror virkelig at jeg mangler noe veldig enkelt, men jeg klarer ikke å finne ut hva. Kan du være så snill å hjelpe meg med dette? Takk

FEIL:

Error: Cannot inject the dependency at position #0 of "ListProjectsServices" constructor. Reason:
    TypeInfo not known for "ProjectsRepository"

Kontroller

export default class ProjectsController {
  public async index(request: Request, response: Response): Promise<void> {
    const listProjectsServices = container.resolve(ListProjectsServices);
    const projects = await listProjectsServices.execute();
    response.json(projects);
  }

Service

@injectable()
export default class ListProjectsServices {

  constructor(
    @inject('ProjectsRepository')
    private ProjectsRepository: IProjectsRepository,
  ) {}

  public async execute(): Promise<Projects[]> {
    const ProjectsList = await this.ProjectsRepository.findAllProjects();
    return ProjectsList;
  }
}

Container - for å opprette injeksjonstokenet

container.registerSingleton<IProjectsRepository>(
  'ProjectsRepository',
  ProjectsRepository,
);

Repository - Merk argumentet extra_details i konstruktøren

etter å ha lagt det til, oppstår problemet

@EntityRepository(Projects)
export default class ProjectsRepository implements IProjectsRepository {
  private ormRepository: Repository<Projects>;

  constructor(extra_details?: object) {
    this.ormRepository = getRepository(Projects);
  }
[...]

Svar #1

I dag gikk jeg gjennom det samme problemet. Les denne artikkelen om sirkulære avhengigheter. Den forteller oss å bruke delay-funksjonen importert fra tsyringe. I artikkelen forteller han oss å bruke delay inne i konstruktøren. Men du, som meg, sender ikke objektet direkte i inject, men en registrert nøkkel. Da må du bruke delay i container-filen din, rundt repository-objektet, prøv dette:

import { container, delay } from 'tsyringe';

container.registerSingleton<IProjectsRepository>(
  'ProjectsRepository',
  delay(() => ProjectsRepository),
);

Sett inn forsinkelsen i alle injeksjonene dine som avhenger av et asynkront lager

Det kan også være en feil i seo ormconfig.json, i egenskapen entities. Sørg for at stien peker til dine entities:

"entities": [
  "./src/modules/**/infra/typeorm/entities/*.ts"
],

Svar #2

Vi hadde det samme problemet her, og vi ønsket ikke å måtte bruke forsinkelsesfunksjonen i kontrolleren fordi vi da ville bryte prinsippet for avhengighetsinjeksjon... En måte å løse problemet på er å importere din "Container"-fil inn i hovedprosjektfilen, i vårt tilfelle kalt "server.ts", og installere et bibliotek kalt "reflect-metadata".

server.ts:

import * as dotenv from 'dotenv';

dotenv.config();

import express from 'express';
import 'express-async-errors';
import 'reflect-metadata'; // here is reflect-metadata import!
import config from './config/application';
import './infra/container'; // here is container import!
import { errorHandler } from './infra/http/middlewares/errorHandler';
import useSwagger from './infra/http/middlewares/swagger';
import { routes } from './infra/http/routes';
import { morganMiddleware } from './infra/logging/morgan';

export const app = express();

app.use(morganMiddleware);
app.use(express.json());
app.use(`${config.prefix}/api`, routes);
app.use(`${config.prefix}`, express.static('public'));
useSwagger(`${config.prefix}/api/docs`, app);
app.all(`${config.prefix}`, (_, res) => res.redirect(`${config.prefix}/api/docs`));
app.use(errorHandler);

container/index.ts:

import { container } from 'tsyringe';
import { RecurrenceNotificationUseCase } from '../../application/useCases/RecurrenceNotificationUseCase';
import { PubSubImplementation } from '../pubsub/PubSubImplementation';

container.registerSingleton('IPubSub', PubSubImplementation);
container.registerSingleton('IRecurrenceNotificationUseCase', RecurrenceNotificationUseCase);

Relaterte artikler