2017-02-01 3 views
1

Я использую InversifyJS для установки своего рода динамического связывания и запуска его на NodeJS. Проблема в том, что я получаю ошибки, но без сообщений и только stacktrace.InversifyJS: Ошибка при извлечении объекта из контейнера

Main класса

export class Main { 
    public static getCalculator(config: string): Calculator { 
     try { 
      var container: Container = new KeyFeatureContainer(config).getContainer(); 
      debugger; 
      // error here ! 
      return container.get<Calculator>(TYPES.Calculator); 
     } catch (error) { 
      debugger; 
      return null; 
     } 
    } 
} 

Этот класс вызывает KeyFeatureContainer с json строкой, используемой для настройки всех привязок (в сортировках динамического пути), а затем извлекает контейнер.

KeyFeatureContainer класса

export class KeyFeatureContainer { 
    private _container: Container; 

    public constructor(config: string) { 
     var jsonConfig: any[] = JSON.parse(config); 

     this._container = new Container(); 
     this._container.bind<Calculator>(TYPES.Calculator).to(KeyFeatureCalculator); 

     for (var i = 0; i < jsonConfig.length; i++) { 
      if (jsonConfig[i].active) { 
       this.parseConfigKeyFeatures(jsonConfig[i].id); 
       this.parseConfigParams(jsonConfig[i].params); 
      } 
     } 
    } 

    public getContainer(): Container { 
     debugger; 
     return this._container; 
    } 

    private parseConfigKeyFeatures(id: string): void { 
     var keyFeatureContainerModule: ContainerModule = rootContainer.get<KeyFeatureContainerModule>(id).getContainerModule(); 

     if (keyFeatureContainerModule != null) 
      this._container.load(keyFeatureContainerModule); 
    } 

    private parseConfigParams(params: Array<{ name: string, value: any }>): void { 
     for (var param of params) 
      this._container.bind(param.name).to(param.value); 
    } 
} 

Этот класс принимает конфигурацию и загружает json, следуя идентификатор, ContainerModule, который содержит связывание между интерфейсом и конкретной реализацией. rootContainer указывает ContainerModule для получения следующего идентификатора.

rootContainer

var rootContainer: Container = new Container(); 

rootContainer.bind<KeyFeatureContainerModule>(KEYFEATURES.DrugHoliday).to(DrugHolidayContainerModule); 
rootContainer.bind<KeyFeatureContainerModule>(KEYFEATURES.MissingDay).to(MissingDayContainerModule); 

export default rootContainer; 

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

@injectable() 
export class MissingDayKeyFeature implements KeyFeature { 
    @inject(PARAMS.MissingDayParams.NbIntakesLimit) 
    private _nbIntakesLimit: number; 

    @inject(PARAMS.MissingDayParams.ExtraParamA) 
    private _extraParamA: any; 

    @inject(PARAMS.MissingDayParams.ExtraParamB) 
    private _extraParamB: any; 

    public init(): void { 
     console.log("init() at MissingDay"); 

     console.log("nbIntakesLimit = " + this._nbIntakesLimit); 
     console.log("extraParamA = " + this._extraParamA); 
     console.log("extraParamB = " + this._extraParamB); 
    } 

    public calculate(): void { 
     console.log("calculate() at MissingDay"); 
    } 

    public finish(): void { 
     console.log("finish() at MissingDay"); 
    } 
} 

@injectable() 
export class MissingDayContainerModule implements KeyFeatureContainerModule { 
    public getContainerModule(): ContainerModule { 
     return new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind) => { 
      bind<KeyFeature>(TYPES.KeyFeature).to(MissingDayKeyFeature); 
     }); 
    } 
} 

И, наконец, ServiceIdentifiers используется для установки целые (разделенные файлы)

let TYPES = { 
    KeyFeature: "KeyFeature", 
    Calculator: "Calculator" 
} 

export default TYPES; 

let PARAMS = { 
    DrugHolidayParams: { 
     NbDaysLimit: "nbDaysLimit", 
     ExtraParamA: "extraParamDHA", 
     ExtraParamB: "extraParamDHB" 
    }, 
    MissingDayParams: { 
     NbIntakesLimit: "nbIntakesLimit", 
     ExtraParamA: "extraParamMDA", 
     ExtraParamB: "extraParamMDB" 
    } 
} 

export default PARAMS; 

let KEYFEATURES = { 
    MissingDay: "MissingDayKeyFeature", 
    DrugHoliday: "DrugHolidayKeyFeature" 
} 

export default KEYFEATURES; 

Наконец JSON вход (отформатирован для удобства)

[{ 
     "id": "DrugHolidayKeyFeature", 
     "active": true, 
     "params": [{ 
       "name": "nbDaysLimit", 
       "value": 3 
      }, { 
       "name": "extraParamDHA", 
       "value": "DHA" 
      }, { 
       "name": "extraParamDHB", 
       "value": "DHB" 
      } 
     ] 
    }, { 
     "id": "MissingDayKeyFeature", 
     "active": false, 
     "params": [{ 
       "name": "nbIntakesLimit", 
       "value": 0 
      }, { 
       "name": "extraParamMDA", 
       "value": "MDA" 
      }, { 
       "name": "extraParamMDB", 
       "value": "MDB" 
      } 
     ] 
    } 
] 

Я использую простой Test скрипт только для вывода значения и посмотреть, если все переплеты сделано правильно

import { Main } from "./Main"; 
var json: string = *json above*; 
Main.getCalculator(json).calculate(); 

Но я в конечном итоге с этой ошибкой

Error 
<  at _createSubRequests (D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\node_modules\inversify\lib\planning\planner.js:106:19) 
<  at Object.plan (D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\node_modules\inversify\lib\planning\planner.js:125:5) 
<  at D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\node_modules\inversify\lib\container\container.js:205:37 
<  at Container._get (D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\node_modules\inversify\lib\container\container.js:198:44) 
<  at Container.get (D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\node_modules\inversify\lib\container\container.js:163:21) 
<  at Function.getCalculator (D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\transpiled\KFCalc\Main.js:9:30) 
<  at Object.<anonymous> (D:\Projects\226RD\nodejs\phantomjs_2016_by_DM\final\transpiled\KFCalc\Test.js:4:13) 
<  at Module._compile (module.js:573:32) 
<  at Object.Module._extensions..js (module.js:582:10) 
<  at Module.load (module.js:490:32) 

Нет никакой информации о том, что происходит, и я не могу понять, что я сделал неправильно. Я не могу get<Calculator> ни get<KeyFeature>, но если я делаю:

container.isBound(TYPES.Calculator) // returns true !!! 

и то же самое относится ко всем связанным пунктам.

Спасибо за любые указатели, у меня нет идей.

+-- @types/[email protected] 
+-- [email protected] 
+-- [email protected] 
+-- [email protected] 

EDIT: Забыли KeyFeatureCalculator

@injectable() 
export class KeyFeatureCalculator implements Calculator { 
    // multi-injection of bound key features 
    private _keyFeatureCalculators: KeyFeature[] = []; 

    public constructor(@multiInject(TYPES.KeyFeature) keyFeatureCalculators: KeyFeature[]) { 
     this._keyFeatureCalculators = keyFeatureCalculators; 
    } 

    public calculate(): void { 
     console.log("calculate() at KeyFeatureCalculator"); 

     for (var calculator of this._keyFeatureCalculators) { 
      calculator.init(); 
      calculator.calculate(); 
      calculator.finish(); 
     } 
    } 
} 

Кроме того, все мои файлы (или почти) импорт inject, injectable из inversify, а также импорт разрешен reflect-metadata

ответ

1

Ошибка: Для тех, кто не заплатил внимание, каждый объект KeyFeature имеет свои свойства, а их типы - number или any.Поскольку значения извлекаются из моего JSON, они набираются как any, и, таким образом, компилятор не предупреждает меня, что привязка bind(xxx).to(yyy) требует быть элементом newable!

Таким образом, в моем примере yyy был чем-то вроде 3, который является номером и, следовательно, не ограничен. Я перешел на bind(xxx).toConstantValue(yyy), и все работает!

Смежные вопросы