У меня есть следующее:
//Editor.TS
let values = await Promise.all([Theme.getTheme(config.theme), I18n.getI18n(config.i18n)]);
//Set up DI container
this.services = new Container();
decorate(injectable(), EventEmitter);
this.services.bind<IContext>(TYPES.Context).toConstantValue(this);
this.services.bind<Theme>(TYPES.Theme).toConstantValue(values[0]);
this.services.bind<I18n>(TYPES.I18n).toConstantValue(values[1]);
this.services.bind<any>(TYPES.Data).toConstantValue(data);
this.services.bind<Toolbox>(TYPES.Toolbox).to(Toolbox).inSingletonScope();
this.services.bind<Workspace>(TYPES.Workspace).to(Workspace).inSingletonScope();
Вызов this.services.get<I18n>(TYPES.I18n);
работает безупречно, если он выполняет ту же функцию, что и код выше. Тем не менее, у меня есть система плагинов, где каждый плагин встроен (с веб-пакетом) в свою собственную библиотеку. Идея заключается в том, что вы подключаете только те плагины, которые вам нужны, чтобы не переполнять основную библиотеку вещами, которые люди могут никогда не использовать.
В любом случае конструктор плагинов выглядит так:
//APlugin.ts
constructor(config, services: Container) {
this.currentLang = this.defaultLang = config.defaultLanguage;
this.supportedLangs = config.supportedLanguages;
this.i18n = services.get<I18n>(TYPES.I18n);
this.context = services.get<IContext>(TYPES.Context);
//Editor Events
this.context.on("dataGenerating", e => this.onDataGenerating());
this.context.on("dataGenerated", data => this.onDataGenerated(data));
}
Как видите, плагин принимает анонимный объект и экземпляр Container
. Идея заключается в том, чтобы позволить разработчику плагина извлекать любые необходимые ему зависимости из контейнера. Запись зависимостей непосредственно в конструктор не возможна по причинам, которые я бы предпочел не go.
Плагины создаются следующим образом:
//Editor.ts
loadPlugin(plugin): IEditorPlugin {
let instance;
if (Array.isArray(plugin))
instance = new plugin[0](plugin[1], this.services);
else
instance = new plugin[0](this.services);
this.plugins.push(instance);
if (typeof instance.getMenuDom === 'function')
this.workspace.addButton(instance.getMenuDom());
return instance;
}
Здесь * Параметр 1016 * может быть либо constructor
, либо [constructor, config: any]
Так что проблема в том, что при работе конструктора плагина я получаю следующую ошибку:
Uncaught (в обещании ) Ошибка: не найдено соответствующих привязок для serviceIdentifier: Symbol (I18n)
Помните, что точный такой же вызов get
, только в той же функции, что и container
определяется, работает просто отлично.
Если я отлаживаю и ломаю this.i18n = services.get<I18n>(TYPES.I18n);
в APlugin.ts, я вижу:
Так что это выглядит как container
настроен и работает правильно, свойство _bindingDictionary
содержит ссылку на TYPES.I18n
. Следует также упомянуть, что эта проблема возникает с всеми привязками. Замена get<I18n>
на любой другой связанный тип приводит к той же ошибке.
Я провел некоторое копание, и кажется, что точка отказа находится в функции getBindings
:
Сбой вызова bindingDictionary.hasKey
, хотя ясно, что результат должен быть true
.