Inversify js: передача контейнера другому объекту приводит к сбою разрешения привязки - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть следующее:

//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, я вижу: enter image description here

Так что это выглядит как container настроен и работает правильно, свойство _bindingDictionary содержит ссылку на TYPES.I18n. Следует также упомянуть, что эта проблема возникает с всеми привязками. Замена get<I18n> на любой другой связанный тип приводит к той же ошибке.

Я провел некоторое копание, и кажется, что точка отказа находится в функции getBindings: enter image description here enter image description here

Сбой вызова bindingDictionary.hasKey, хотя ясно, что результат должен быть true.

1 Ответ

0 голосов
/ 21 февраля 2020

Причина в том, что вызов Symbol(..) создает уникальный символ каждый раз, когда он вызывается , независимо от того, является ли аргумент одинаковым или нет.

Ключ должен был использовать Symbol.for(..) , Это создает символ и сохраняет его в глобальном кэше символов или возвращает этот символ, если он уже существует. Это выживет во всех контекстах.

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