Hey Community
I try to create an instance of a service object right after binding. It might be an XY Problem so I`ll try to describe what i want to achieve.
I have an AssignmentModelService
on the browser side which acts as a presentation model. This service communicates with the node backend and emits events on state changes. Widgets register listeners and update the presentation. Nothing special, I guess. Now it´s the case that I have event listeners which do not belong to any of the widgets. For this purpose I created an CommonEventHandlerService
:
// my-extension/src/browser/common-event-handler/common-event-handler-service.ts
@injectable()
export class CommonEventHandlerService {
@inject(WorkspaceService)
protected readonly workspaceService: WorkspaceService;
@inject(EditorManager)
protected readonly editorManager: EditorManager;
@inject(AssignmentModelService)
private readonly assignmentModelService: AssignmentModelService;
@postConstruct()
protected init(): void {
// Register AssignmentModelChangeEvent listener
this.assignmentModelService.onDidStateChange(event => {
event.assignmentDidChange && this.onAssignmentDidChange();
});
}
private async onAssignmentDidChange(): Promise<void> {
// In case of an assignment change all open editors for the previous assignment
// must be closed. After that an editor window is opened for all loaded 'src' files.
if (this.workspaceService.opened) {
if (this.editorManager.all.length > 0) {
await this.editorManager.closeAll({ save: false });
}
const workspaceRoot = this.workspaceService.workspace!.resource.path.toString();
const srcFiles = this.assignmentModelService.getFilesByType('src');
srcFiles.forEach(file =>
this.editorManager.open(new URI([workspaceRoot, file.path].join('/')))
);
}
}
}
I bind it as usual…
// my-extension/src/browser/my-extension-frontend-module.ts
export default new ContainerModule(bind => {
...
bind(CommonEventHandlerService).toSelf().inSingletonScope();
...
});
but unlike my other classes I don’t see the need for a Contribution class and nothing is requiring a reference to my CommonEventHandlerService
. Therefor inversify is never creating an instance when resolving the dependencies.
I think of this as a pretty common usecase but I “did my research” and I am struggling to find any people having the same problem. Which, of course, makes me think that I am getting something (about DI) fundamentally wrong?!
Other people using inversify force the instantiation by calling get()
on the DI container, but I did not find a way to access the container itself from my extension.
container.bind(MyClass).toSelf();
const myClass = container.get(MyClass);
I would highly appreciate any hints or thoughts on this,
thank you in advance,
Leo
Current workaround
Everything does work as expected if I create a CommonEventHandlerContribution
which only holds a reference to the CommonEventHandlerService
. But this does not seem right to me and also Typescript is complaining then:
... /common-event-handler-contribution.ts(6,14): error TS2559: Type 'CommonEventHandlerContribution' has no properties in common with type 'FrontendApplicationContribution'.
... /common-event-handler-contribution.ts(8,20): error TS6133: 'commonEventHandlerService' is declared but its value is never read.
// my-extension/src/browser/common-event-handler/common-event-handler-contribution.ts
@injectable()
export class CommonEventHandlerContribution implements FrontendApplicationContribution {
@inject(CommonEventHandlerService)
private readonly commonEventHandlerService: CommonEventHandlerService;
}
// my-extension/src/browser/my-extension-frontend-module.ts
export default new ContainerModule(bind => {
...
bind(CommonEventHandlerService).toSelf().inSingletonScope();
bind(CommonEventHandlerContribution).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(CommonEventHandlerContribution);
...
});