Приложение cra sh при вызове container.get () в конструкторе абстрактного класса - PullRequest
1 голос
/ 01 мая 2020

В настоящее время я пытаюсь реализовать базовый класс, который имеет несколько свойств. Все свойства, кроме одного, вводятся через конструктор с помощью тега @Inject Inversify JS. Я также получаю экземпляр через функцию container.Get () в конструкторе. Когда я запускаю свое приложение, все в порядке, но когда приложение получает запрос, приложение вылетает без ошибки.

enter image description here

Базовый класс

/**
 * Base class for all intent logic
 */
@injectable()
export default abstract class IntentBase implements IIntent {
  protected logger: ILogger;
  protected responseService: IResponseService;
  protected contextService: IContextService;
  protected fallbackIntent: IIntent;
  protected responseBuilder: IResponseBuilder;

  /**
   * Constructor
   * @param logger logger
   * @param responseService response service
   * @param contextService context service
   */
  constructor(
    @inject(TYPES.WinstonLogger) logger: ILogger,
    @inject(TYPES.ResponseService) responseService: IResponseService,
    @inject(TYPES.ContextService) contextService: IContextService,
    @inject(TYPES.ResponseBuilder) responseBuilder: IResponseBuilder,
  ) {
    this.logger = logger;
    this.responseService = responseService;
    this.contextService = contextService;
    this.responseBuilder = responseBuilder;
    this.fallbackIntent = container.get(TYPES.DefaultFallbackIntent); // <-- container.Get() line
  }

  /**
   * Override the standard fallback logic for an intent.
   * @param fallback fallback to set
   */
  setFallback(fallback: IIntent): void {
    this.fallbackIntent = fallback;
  }

Когда я раскомментирую строку container.get (TYPES.DefaultFallbackIntent), мое приложение может получать запросы, как обычно, и не обрабатывает sh. Причина, по которой я пробую эту настройку внедрения, заключается в том, что я хотел бы установить поведение по умолчанию для каждого дочернего класса в конструкторе.

У кого-нибудь есть объяснение, почему я не могу внедрить этот класс? Заранее спасибо

Обновление

inversify.config.ts

import DefaultFallbackIntent from "./src/bot/intents/fallbacks/defaultFallbackIntent";
import TextResponseRepository from "./src/repositories/textResponseRepository";
import SsmlResponseRepsitory from "./src/repositories/ssmlResponseRepository";
import ContextService from "./src/services/contextService";
import GoogleResponseBuilder from "./src/builders/googleResponseBuilder";

const container = new Container();

container.bind<IGoogleAssistantController>(TYPES.GoogleController).to(GoogleAssistantController);
container.bind<IResponseService>(TYPES.ResponseService).to(ResponseSerivce);
container.bind<IContextService>(TYPES.ContextService).to(ContextService);
container.bind<IResponseRepository>(TYPES.TextResponseRepository).to(TextResponseRepository);
container.bind<IResponseRepository>(TYPES.SsmlResponseRepository).to(SsmlResponseRepsitory);
container.bind<ILogger>(TYPES.WinstonLogger).to(WinstonLogger);

container.bind<IIntent>(TYPES.WelcomeIntent).to(WelcomeIntent);
container.bind<IIntent>(TYPES.DefaultFallbackIntent).to(DefaultFallbackIntent);
container.bind<IResponseBuilder>(TYPES.ResponseBuilder).to(GoogleResponseBuilder);

export { container };

Стандартное намерение отступления

/**
 * Default fallback intent class
 */
@injectable()
export default class DefaultFallbackIntent extends IntentBase {
  invoke(conv: DialogflowConversation): DialogflowConversation {
    const response = this.responseService.getResponse("defaultFallback");
    return conv.ask(response);
  }
}

1 Ответ

1 голос
/ 01 мая 2020

Чтобы container.get(<Type>) работал, <Type> должен быть привязан к контейнеру в некоторой точке. В вашей композиции root (где вы установили свой контейнер) вы можете создать эту привязку:

const container = new Container();
container.bind<IIntent>(TYPES.DefaultFallbackIntent)).to(<TheDefaultFallbackIntentClass>);

РЕДАКТИРОВАТЬ:

Из обсуждения в комментариях кажется, что DefaultFallbackIntent наследование с IntentBase проблема, потому что в момент создания экземпляра DefaultFallbackIntent (посредством его привязки) такого экземпляра в контейнере не существует, когда выполняется базовый конструктор.

Обходной путь будет чтобы не наследовать от IntentBase, а просто реализовать интерфейс и установить обязательные поля в этом классе:

/**
 * Default fallback intent class
 */
@injectable()
export default class DefaultFallbackIntent implements IIntent {
protected logger: ILogger;
  private responseService: IResponseService;
  private contextService: IContextService;
  private fallbackIntent: IIntent;
  private responseBuilder: IResponseBuilder;

  invoke(conv: DialogflowConversation): DialogflowConversation {
    const response = this.responseService.getResponse("defaultFallback");
    return conv.ask(response);
  }
}

Однако, лучшим решением было бы два создать еще один суперкласс, который содержит все необходимые поля и резервное намерение по умолчанию, и другие, чтобы уменьшить дублирующийся код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...