简体   繁体   English

Inversify 无法注入 class 依赖项

[英]Inversify cannot inject class with dependencies

I started a new typescript project based an old project of mime (which started as plain javascript) and I can't get any non-trivial injection working.我开始了一个新的 typescript 项目,该项目基于一个旧的 mime 项目(以普通 javascript 开始),但我无法进行任何重要的注入工作。 I know about nothing about babel configuration (because of staring with create-react-app).我对 babel 配置一无所知(因为盯着 create-react-app)。 I tried the recommended compilerOptions and it didn't work either..... my setup may be a mess, but that's how it evolved.我尝试了推荐的 compilerOptions ,但它也没有用.....我的设置可能一团糟,但这就是它的演变方式。

Feel free to get the whole project from github (get it and run npm install && npm start ) or continue reading.随意从github获取整个项目(获取并运行npm install && npm start )或继续阅读。

import 'reflect-metadata';
import { Container } from 'inversify';
import React from 'react';
import ReactDOM from 'react-dom';
import { injectable } from 'inversify';

@injectable()
export class Simple {
}

@injectable()
export class Composed {
    simple: Simple;

    // ERROR: Module parse failed: Unexpected character '@'
    // constructor(@inject simple: Simple) {
    //  this.simple = simple;
    // }

    // Error: Missing required @inject or @multiInject annotation in: argument 0 in class Composed.
    constructor(simple: Simple) {
        this.simple = simple;
    }
}

const container = new Container();
container.bind(Simple).toSelf();
container.bind(Composed).toSelf();
console.log(container.get(Composed));

function Main() {
    return <div>
        {JSON.stringify(container.get(Composed))}
    </div>;
}

ReactDOM.render(<Main/>, document.getElementById('root'));

package.json package.json

{
    "name": "inversify-problem",
    "version": "0.0.1",
    "description": "",
    "private": true,
    "dependencies": {
        "@material-ui/core": "^4.9.8",
        "@material-ui/icons": "^4.9.1",
        "array.prototype.flatmap": "^1.2.3",
        "customize-cra": "^0.9.1",
        "deep-equal": "^2.0.1",
        "eslint": "^6.8.0",
        "inversify": "^5.0.1",
        "json-stable-stringify": "^1.0.1",
        "mobx": "^5.15.4",
        "mobx-decorators": "^6.0.1",
        "mobx-react": "^6.1.8",
        "mobx-state-tree": "^3.15.0",
        "notistack": "^0.9.9",
        "react": "^16.13.1",
        "react-app-polyfill": "^1.0.6",
        "react-app-rewire-mobx": "^1.0.9",
        "react-app-rewired": "^2.1.5",
        "react-dom": "^16.13.1",
        "reflect-metadata": "^0.1.13",
        "resize-observer-polyfill": "^1.5.1",
        "shallowequal": "^1.1.0",
        "styled-components": "^5.0.1",
        "ts-enum-util": "^4.0.1"
    },
    "devDependencies": {
        "babel-plugin-import": "^1.13.0",
        "babel-plugin-styled-components": "^1.10.7",
        "@types/classnames": "^2.2.10",
        "@types/deep-equal": "^1.0.1",
        "@types/json-stable-stringify": "^1.0.32",
        "@types/jest": "^25.1.4",
        "@types/node": "^13.9.8",
        "@types/react": "^16.9.29",
        "@types/react-dom": "^16.9.5",
        "eslint-plugin-unused-imports": "^0.1.2",
        "tslint-etc": "^1.10.1",
        "react-scripts": "^3.4.1",
        "typescript": "^3.8.3"
    },
    "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test",
        "eslint": "eslint --fix $(find src -name '*.ts' -o  -name '*.tsx')",
        "eject": "react-scripts eject"
    },
    "eslintConfig": {
        "extends": "react-app",
        "parserOptions": {
            "ecmaFeatures": {
                "legacyDecorators": true
            }
        }
    },
    "browserslist": [
        ">0.2%",
        "not dead",
        "not ie <= 11",
        "not op_mini all"
    ]
}

tsconfig.json tsconfig.json

{
    "compilerOptions": {
        "target": "ES5",
        "sourceMap": true,
        "downlevelIteration": true,
        "importHelpers": true,
        "lib": [
            "dom",
            "dom.iterable",
            "esnext",
            "es6",
            "webworker",
            "es2015.collection",
            "es2015.iterable",
            "es2019"
        ],
        "types": [
            "node",
            "reflect-metadata"
        ],
        "allowJs": false,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "strictNullChecks": true,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "noImplicitAny": true,
        "noEmitOnError": false,
        "incremental": false,
        "jsx": "preserve",
        "noEmit": true
    },
    "include": [
        "src/index.tsx",
        "src/mg/extras.d.ts"
    ]
}

config-overrides.js配置覆盖.js

const {
    override,
} = require("customize-cra");

module.exports = override(
);

Debugging调试

I tried to debug the problem, but found not much out.我试图调试问题,但发现不多。 There are no metadata, no attempt is made to parse Function.prototype.toString() like in this answer .没有元数据,没有像这个答案那样尝试解析 Function.prototype.toString() 。 There's something wrong with my configuration, but that thing is pretty opaque to me.我的配置有问题,但那件事对我来说很不透明。

You are struggling because the react babel config does not allow decorators, so what you can do is:你正在挣扎,因为 react babel 配置不允许装饰器,所以你可以做的是:

$ npm run eject
$ npm install react-scripts # if you use an older npm installation then you need to add --save
$ npm install -D @babel/plugin-proposal-decorators 
$ npm install -D babel-plugin-parameter-decorator

Your package.json is now expanded with a lot of options, find the babel section and change it as follows:你的package.json现在扩展了很多选项,找到babel部分并更改如下:

  "babel": {
    "plugins": [
      [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        "babel-plugin-parameter-decorator"
      ]
    ],
    "presets": [
      // ...
      ["@babel/preset-typescript", { "onlyRemoveTypeImports": true }]
    ]
  }

now you can at least use field injection as follows:现在您至少可以按如下方式使用字段注入:

// ...
import { inject, injectable } from 'inversify';
// ...

@injectable()
class Composed {
    private readonly simple: Simple;

    public constructor(@inject(Simple) simple: Simple) {
        this.simple = simple;
    }
}

//...

The solution is based on this:解决方案基于此:

For more info on why decorators isn't supported:有关为什么不支持装饰器的更多信息:

I had the same solution as posted but instead of using package.json , I used config-overrides.js :我有与发布的相同的解决方案,但我没有使用package.json ,而是使用了config-overrides.js

const {
  override,
  addDecoratorsLegacy,
  addBabelPlugin,
} = require("customize-cra");

module.exports = override(
  addDecoratorsLegacy(),
  addBabelPlugin("babel-plugin-parameter-decorator")
);

To be honest, I didn't like this solution so I didn't post it...老实说,我不喜欢这个解决方案,所以我没有发布它......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM