如何在环回4中进行方法注入

问题描述

我想创建一种方法checkAddressEnterContestBefore来检查某些要求。此功能需要连接到数据库MysqL),但我无法注入存储库。 在这种情况下我该怎么办?

import { Contest } from '../models';
import { CONTEST_STATUS } from './constants';
import { ContestEntryRepository } from '../repositories';
import { inject } from '@loopback/core';

export function checkEnterContest(contest: Contest,address: string): boolean {
    ....
    if (!checkAddressEnterContestBefore(contest,address)) return false;
    ...
    return true;
}

export async function checkAddressEnterContestBefore(
    @inject(ContestEntryRepository) contestEntryRepository: ContestEntryRepository,contest: Contest,address: string): Promise<boolean> {
    const contestEntry = await contestEntryRepository.findOne({
        where: {
            and: [
                { contestId: contest.id },{ address: address }
            ]
        }
    });

    return contestEntry == null
}

解决方法

依赖注入分为两个部分:

  1. 使用@inject装饰器装饰接收代码的依赖项,以指定要注入的内容
  2. 此类代码的调用者必须解决IoC容器中的依赖项

在您的代码段中,您正在修饰checkAddressEnterContestBefore以便通过DI接收一些参数(这是上面列表中的第一项)。代码完全可以编译吗? AFAIK,装饰器不能应用于常规函数,只能应用于类成员(静态或实例级别)。

使用静态类方法的示例:

export class CheckAddressEnterContestBefore {
  static async run(
    @inject(ContestEntryRepository) contestEntryRepository: ContestEntryRepository,contest: Contest,address: string): Promise<boolean> {
      const contestEntry = await contestEntryRepository.findOne({
        where: {
            and: [
                { contestId: contest.id },{ address: address }
            ]
        }
      });

      return contestEntry == null
  }
}

现在checkEnterContest尚未实现依赖项注入/解析(上面列表中的第二项)。

LoopBack提供了一个辅助函数invokeMethod,您可以使用该函数来调用具有依赖项注入的方法。您将需要当前的Context对象作为从中获取依赖项的源。

import {invokeMethod} from '@loopback/core';

export function checkEnterContest(ctx: Context,address: string): boolean {
    ....
    const checkResult = await invokeMethod(
      CheckAddressEnterContestBefore,'run',// context for resolving dependencies
      ctx,// additional (non-injected) arguments
      [contest,address],);

    if (!checkResult) return false;
    ...
    return true;
}

就我个人而言,我认为它是一种反模式,可以从代码库内部的上下文中解析依赖关系。相反,我建议使用常规的函数/方法参数在代码库的不同部分之间传递依赖关系,并且仅在顶层(通常在控制器方法中)使用基于@inject的依赖关系注入。

这将使您的代码更易于单独测试,因为每个函数都清楚了它需要的依赖项,并且如果您的测试未提供所有必需的依赖项,则编译器会在编译时警告您。当您从上下文中解析依赖项时,您将仅在运行时发现缺少的依赖项,而这些依赖项由于您的测试未在上下文中绑定它们而无法解决。

话虽如此,这就是我如何重写您的代码:

export function checkEnterContest(
  contestEntryRepository: ContestEntryRepository,address: string
): boolean {
    ....
    if (!checkAddressEnterContestBefore(contestEntryRepository,contest,address)) return false;
    ...
    return true;
}

export async function checkAddressEnterContestBefore(
  contestEntryRepository: ContestEntryRepository,address: string
): Promise<boolean> {
    const contestEntry = await contestEntryRepository.findOne({
        where: {
            and: [
                { contestId: contest.id },{ address: address }
            ]
        }
    });

    return contestEntry == null
}

根据您喜欢的代码结构方式,将checkEnterContestcheckAddressEnterContestBefore作为ContestEntryRepository方法可能会更好。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...