在抽象 class 的构造函数中调用 container.get() 时应用程序崩溃
Application crash when calling container.get() in abstract class's constructor
我目前正在尝试实现一个具有多个属性的基础 class。除了一个 属性 之外,所有的都使用 InversifyJS 的 @Inject 标签通过构造函数注入。我还通过构造函数中的 container.Get() 函数获取了一个实例。当我 运行 我的应用程序一切正常时,但是当应用程序收到请求时,应用程序崩溃而没有错误。
基础class
/**
* 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) 行时,我的应用程序可以正常接收请求并且不会崩溃。我尝试这种注入设置的原因是因为我想在构造函数中为每个子 class 设置一个默认行为。
有人能解释为什么我似乎无法注入这个 class 吗?
提前致谢
更新
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);
}
}
为了 container.get(<Type>)
工作,<Type>
必须在某个时间点 bound 到容器。在您的组合根目录(您设置容器的位置)中,您可以创建此绑定:
const container = new Container();
container.bind<IIntent>(TYPES.DefaultFallbackIntent)).to(<TheDefaultFallbackIntentClass>);
编辑:
从评论中的讨论看来,DefaultFallbackIntent
继承自 IntentBase
是问题所在,因为当时 DefaultFallbackIntent
被实例化(通过绑定),没有执行基本构造函数时,容器中不存在这样的实例。
解决方法是不从 IntentBase
继承,只实现接口并在此 class 中设置必填字段:
/**
* 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);
}
}
但是,更好的解决方案是创建另一个超级 class,其中包含默认回退意图和其他意图的所有必填字段,以减少重复代码。
我目前正在尝试实现一个具有多个属性的基础 class。除了一个 属性 之外,所有的都使用 InversifyJS 的 @Inject 标签通过构造函数注入。我还通过构造函数中的 container.Get() 函数获取了一个实例。当我 运行 我的应用程序一切正常时,但是当应用程序收到请求时,应用程序崩溃而没有错误。
基础class
/**
* 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) 行时,我的应用程序可以正常接收请求并且不会崩溃。我尝试这种注入设置的原因是因为我想在构造函数中为每个子 class 设置一个默认行为。
有人能解释为什么我似乎无法注入这个 class 吗? 提前致谢
更新
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);
}
}
为了 container.get(<Type>)
工作,<Type>
必须在某个时间点 bound 到容器。在您的组合根目录(您设置容器的位置)中,您可以创建此绑定:
const container = new Container();
container.bind<IIntent>(TYPES.DefaultFallbackIntent)).to(<TheDefaultFallbackIntentClass>);
编辑:
从评论中的讨论看来,DefaultFallbackIntent
继承自 IntentBase
是问题所在,因为当时 DefaultFallbackIntent
被实例化(通过绑定),没有执行基本构造函数时,容器中不存在这样的实例。
解决方法是不从 IntentBase
继承,只实现接口并在此 class 中设置必填字段:
/**
* 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);
}
}
但是,更好的解决方案是创建另一个超级 class,其中包含默认回退意图和其他意图的所有必填字段,以减少重复代码。