Skip to content

Commit 1090d9e

Browse files
Merge pull request #4 from leonardfactory/inversifyjs-property-injector
Support InversifyJS property injection
2 parents a27b66d + b263fcd commit 1090d9e

File tree

9 files changed

+2338
-0
lines changed

9 files changed

+2338
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ yarn-error.log*
77

88
# Emit
99
lib
10+
examples/**/lib
1011

1112
# Runtime data
1213
pids

.vscode/launch.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
// Usare IntelliSense per informazioni sui possibili attributi.
3+
// Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti.
4+
// Per ulteriori informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "attach",
10+
"name": "Attach",
11+
"port": 9229
12+
}
13+
]
14+
}

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,37 @@ With `.babelrc`:
106106
}
107107
```
108108

109+
### Usage with [InversifyJS](http://inversify.io)
110+
111+
If you are using normal dependency injection letting Inversify **create your instances**, you should be fine with all kind of decorators.
112+
113+
Instead, if you are using **property injection**, when [the container does not
114+
create the instances](https://github.com/inversify/InversifyJS/blob/master/wiki/property_injection.md#when-we-cannot-use-inversifyjs-to-create-an-instance-of-a-class),
115+
you would likely encounter errors since babel
116+
decorators are not exactly the same as TypeScript.
117+
118+
You can fix it by _enhancing property decorators_ with the following function:
119+
120+
```ts
121+
import getDecorators from 'inversify-inject-decorators';
122+
// setup the container...
123+
let { lazyInject: originalLazyInject } = getDecorators(container);
124+
125+
// Additional function to make properties decorators compatible with babel.
126+
function fixPropertyDecorator<T extends Function>(decorator: T): T {
127+
return ((...args: any[]) => (
128+
target: any,
129+
propertyName: any,
130+
...decoratorArgs: any[]
131+
) => {
132+
decorator(...args)(target, propertyName, ...decoratorArgs);
133+
return Object.getOwnPropertyDescriptor(target, propertyName);
134+
}) as any;
135+
}
136+
137+
export const lazyInject = fixPropertyDecorator(originalLazyInject);
138+
```
139+
109140
## Current Pitfalls
110141

111142
- We cannot know if type annotations are just types (i.e. `IMyInterface`) or

examples/inversify/.babelrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"plugins": [
3+
"../../lib/plugin.js",
4+
["@babel/plugin-proposal-decorators", { "legacy": true }],
5+
["@babel/plugin-proposal-class-properties", { "loose": true }]
6+
],
7+
"presets": [
8+
["@babel/preset-env", { "targets": { "node": "current" } }],
9+
"@babel/preset-typescript"
10+
]
11+
}

examples/inversify/package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "inversify",
3+
"version": "0.0.1",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"private": true,
7+
"scripts": {
8+
"build": "babel src -d lib -x '.ts,.tsx'",
9+
"dev": "babel src -w -d lib -x '.ts,.tsx'",
10+
"start": "node lib/index.js"
11+
},
12+
"devDependencies": {
13+
"@babel/cli": "^7.2.3",
14+
"@babel/core": "^7.4.0",
15+
"@babel/plugin-proposal-class-properties": "^7.4.0",
16+
"@babel/plugin-proposal-decorators": "^7.4.0",
17+
"@babel/preset-env": "^7.4.2",
18+
"@babel/preset-typescript": "^7.3.3",
19+
"typescript": "^3.3.4000"
20+
},
21+
"dependencies": {
22+
"inversify": "^5.0.1",
23+
"inversify-inject-decorators": "^3.1.0",
24+
"reflect-metadata": "^0.1.13"
25+
}
26+
}

examples/inversify/src/index.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import 'reflect-metadata';
2+
3+
import getDecorators from 'inversify-inject-decorators';
4+
import { Container, injectable } from 'inversify';
5+
6+
@injectable()
7+
class PrintService {
8+
print(book: Book) {
9+
console.log(`Book "${book.summary}" by ${book.author}.`);
10+
}
11+
}
12+
13+
let container = new Container();
14+
container.bind<PrintService>('PrintService').to(PrintService);
15+
let { lazyInject } = getDecorators(container);
16+
17+
/**
18+
* Additional function to make properties decorators compatible with babel.
19+
*/
20+
function fixPropertyDecorator<T extends Function>(decorator: T): T {
21+
return ((...args: any[]) => (
22+
target: any,
23+
propertyName: any,
24+
...decoratorArgs: any[]
25+
) => {
26+
decorator(...args)(target, propertyName, ...decoratorArgs);
27+
return Object.getOwnPropertyDescriptor(target, propertyName);
28+
}) as any;
29+
}
30+
31+
const lazyInjectFix = fixPropertyDecorator(lazyInject);
32+
33+
class Book {
34+
@lazyInjectFix('PrintService')
35+
private printService!: PrintService;
36+
37+
public constructor(public author: string, public summary: string) {}
38+
39+
public print() {
40+
this.printService.print(this);
41+
}
42+
}
43+
44+
// Book instance is NOT created by InversifyJS
45+
let book = new Book('George Orwell', '1984');
46+
book.print();

examples/inversify/tsconfig.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"compilerOptions": {
3+
"target": "esnext",
4+
"module": "commonjs",
5+
"strict": true,
6+
"allowSyntheticDefaultImports": true,
7+
"esModuleInterop": true,
8+
9+
"experimentalDecorators": true,
10+
"emitDecoratorMetadata": true,
11+
12+
"outDir": "lib",
13+
"rootDir": "src",
14+
"baseUrl": "."
15+
},
16+
"include": ["src/index.ts"]
17+
}

0 commit comments

Comments
 (0)