README.md
# inversify-inject-decorators
[![Join the chat at https://gitter.im/inversify/InversifyJS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/inversify/InversifyJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://secure.travis-ci.org/inversify/inversify-inject-decorators.svg?branch=master)](https://travis-ci.org/inversify/inversify-inject-decorators)
[![Test Coverage](https://codeclimate.com/github/inversify/inversify-inject-decorators/badges/coverage.svg)](https://codeclimate.com/github/inversify/inversify-inject-decorators/coverage)
[![npm version](https://badge.fury.io/js/inversify-inject-decorators.svg)](http://badge.fury.io/js/inversify-inject-decorators)
[![Dependencies](https://david-dm.org/inversify/inversify-inject-decorators.svg)](https://david-dm.org/inversify/inversify-inject-decorators#info=dependencies)
[![img](https://david-dm.org/inversify/inversify-inject-decorators/dev-status.svg)](https://david-dm.org/inversify/inversify-inject-decorators/#info=devDependencies)
[![img](https://david-dm.org/inversify/inversify-inject-decorators/peer-status.svg)](https://david-dm.org/inversify/inversify-inject-decorators/#info=peerDependenciess)
[![Known Vulnerabilities](https://snyk.io/test/github/inversify/inversify-inject-decorators/badge.svg)](https://snyk.io/test/github/inversify/inversify-inject-decorators)
[![NPM](https://nodei.co/npm/inversify-inject-decorators.png?downloads=true&downloadRank=true)](https://nodei.co/npm/inversify-inject-decorators/)
[![NPM](https://nodei.co/npm-dl/inversify-inject-decorators.png?months=9&height=3)](https://nodei.co/npm/inversify-inject-decorators/)
Lazy evaluated property injection decorators.
## Motivation
Some frameworks and libraries take control over the creation of instances
of a given class. For example, React takes control over the creation of
instances of a given React component. This kind of frameworks and libraries
**prevent us from being able to use constructor injection** and as a result
they are not easy to integrate with InversifyJS.
InversifyJS also provides support for property injection but it also
requires the instances of a class to be created by InversifyJS.
The decorators included in this library will allow you to lazy-inject
properties even when the instances of a class are not created by InversifyJS.
This library allows you to integrate InversifyJS with any library or
framework that takes control over the creation of instances of a
given class.
## Installation
You can install `inversify-inject-decorators` using npm:
```
$ npm install inversify inversify-inject-decorators reflect-metadata --save
```
The `inversify-inject-decorators` type definitions are included in the npm module and require TypeScript 2.0.
> :warning: Please note that this library requires support for the ES6 Symbol. You can use the [es6-symbol polyfill](https://www.npmjs.com/package/es6-symbol) as a work arround.
Please refer to the [InversifyJS documentation](https://github.com/inversify/InversifyJS#installation) to learn more about the installation process.
## Caching vs Non Caching Behaviour
By default, the lazy injection mechanism implemented by this will cache all requests to the underlying container.
This means that rebinding or unbinding services to/from service identifiers will not be reflected in the instances into which these services have been injected into. The same holds true for scenarios where you dynamically load/unload container modules and thus either add or remove bindings from your container.
To overcome this limitation, one can now pass an additional boolean parameter to `getDecorators(container: Container, doCache = true)`. When set to `false`, services resolved from the container will no longer be cached and will always be resolved from the container directly, e.g.
```ts
import { Container } from "inversify";
import getDecorators from "inversify-inject-decorators";
const container: Container = new Container();
const { lazyInject } = getDecorators(container, false);
```
## Basic property lazy-injection with `@lazyInject`
The following example showcases how to inject into a property
using the `@lazyInject` decorator:
```ts
import getDecorators from "inversify-inject-decorators";
import { Container, injectable, tagged, named } from "inversify";
let container = new Container();
let { lazyInject } = getDecorators(container);
let TYPES = { Weapon: "Weapon" };
interface Weapon {
name: string;
durability: number;
use(): void;
}
@injectable()
class Sword implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Sword";
}
public use() {
this.durability = this.durability - 10;
}
}
class Warrior {
@lazyInject(TYPES.Weapon)
public weapon: Weapon;
}
container.bind<Weapon>(TYPES.Weapon).to(Sword);
let warrior = new Warrior();
console.log(warrior.weapon instanceof Sword); // true
```
## Named property injection with `@lazyInjectNamed`
The following example showcases how to inject into a named property
using the `@lazyInjectNamed` decorator:
```ts
import getDecorators from "inversify-inject-decorators";
import { Container, injectable, named } from "inversify";
let container = new Container();
let { lazyInjectNamed } = getDecorators(container);
let TYPES = { Weapon: "Weapon" };
interface Weapon {
name: string;
durability: number;
use(): void;
}
@injectable()
class Sword implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Sword";
}
public use() {
this.durability = this.durability - 10;
}
}
@injectable()
class Shuriken implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Shuriken";
}
public use() {
this.durability = this.durability - 10;
}
}
class Warrior {
@lazyInjectNamed(TYPES.Weapon, "not-throwable")
@named("not-throwable")
public primaryWeapon: Weapon;
@lazyInjectNamed(TYPES.Weapon, "throwable")
@named("throwable")
public secondaryWeapon: Weapon;
}
container.bind<Weapon>(TYPES.Weapon).to(Sword).whenTargetNamed("not-throwable");
container.bind<Weapon>(TYPES.Weapon).to(Shuriken).whenTargetNamed("throwable");
let warrior = new Warrior();
console.log(warrior.primaryWeapon instanceof Sword); // true
console.log(warrior.primaryWeapon instanceof Shuriken); // true
```
## Tagged property injection with `@lazyInjectTagged`
The following example showcases how to inject a tagged property
using the `@lazyInjectTagged` decorator:
```ts
import getDecorators from "inversify-inject-decorators";
import { Container, injectable, tagged } from "inversify";
let container = new Container();
let { lazyInjectTagged } = getDecorators(container);
let TYPES = { Weapon: "Weapon" };
interface Weapon {
name: string;
durability: number;
use(): void;
}
@injectable()
class Sword implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Sword";
}
public use() {
this.durability = this.durability - 10;
}
}
@injectable()
class Shuriken implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Shuriken";
}
public use() {
this.durability = this.durability - 10;
}
}
class Warrior {
@lazyInjectTagged(TYPES.Weapon, "throwable", false)
@tagged("throwwable", false)
public primaryWeapon: Weapon;
@lazyInjectTagged(TYPES.Weapon, "throwable", true)
@tagged("throwwable", true)
public secondaryWeapon: Weapon;
}
container.bind<Weapon>(TYPES.Weapon).to(Sword).whenTargetTagged("throwable", false);
container.bind<Weapon>(TYPES.Weapon).to(Shuriken).whenTargetTagged("throwable", true);
let warrior = new Warrior();
console.log(warrior.primaryWeapon instanceof Sword); // true
console.log(warrior.primaryWeapon instanceof Shuriken); // true
```
## Multi-injection into a property with `@lazyMultiInject`
The following example showcases how to multi-inject a property
using the `@lazyMultiInject` decorator:
```ts
import getDecorators from "inversify-inject-decorators";
import { Container, injectable } from "inversify";
let container = new Container();
let { lazyMultiInject } = getDecorators(container);
let TYPES = { Weapon: "Weapon" };
interface Weapon {
name: string;
durability: number;
use(): void;
}
@injectable()
class Sword implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Sword";
}
public use() {
this.durability = this.durability - 10;
}
}
@injectable()
class Shuriken implements Weapon {
public name: string;
public durability: number;
public constructor() {
this.durability = 100;
this.name = "Shuriken";
}
public use() {
this.durability = this.durability - 10;
}
}
class Warrior {
@lazyMultiInject(TYPES.Weapon)
public weapons: Weapon[];
}
container.bind<Weapon>(TYPES.Weapon).to(Sword);
container.bind<Weapon>(TYPES.Weapon).to(Shuriken);
let warrior = new Warrior();
console.log(warrior.weapons[0] instanceof Sword); // true
console.log(warrior.weapons[1] instanceof Shuriken); // true
```