InversityJS is an IoC framework. IoC includes Dependency Injection and Dependency Lookup.

In contrast to class inheritance, inversion of control decouples the parent class from the child class.

Case analysis

import 'reflect-metadata' import { inject, injectable, Container} from 'inversify' const Container = new Container() @injectable() class PopMusic {getName() {return 'PopMusic' }} container.bind('request1').to(PopMusic) @ Injectable () class classmusic {getName() {return 'classmusic'}} container.bind('request2').to(ClassicalMusic) @injectable() class Music { pm: any cm: any constructor( @inject('request1') popMusic: any, @inject('request2') classicalMusic: any) { this.pm = popMusic this.cm = classicalMusic } getName() { const result = this.pm.getName() + this.cm.getName() return result } } container.bind('Plan').to(Music) const music: Any = container.get('Plan') console.log(music.getName()) // Popular music Classical musicCopy the code

The above example can be abstracted as follows:

Dashed lines indicate that injection is possible, but not shown in the code.

The code flow can be summarized as follows:

1. Add all related classes (Music, popMusic, classicMusic) into the container through @ Injectable.

2. Use container.get() to obtain the target object in container.bind().to(target).

3. If the target object has @inject() in its constructor(), inject the corresponding instance (in this case PopMusic and classicalMusic instances) as arguments to the constructor;

Inject /injectable related source code

Inject source code is simplified as follows:

// This is an attribute decorator
function inject(serviceIdentifier) {
  return function (target, targetKey) {
    const metadataValue = { [targetKey]: [Metadata { key: 'inject'.value: serviceIdentifier })] }
    Reflect.defineMetadata('inversify:tagged_props', metadataValue, target.constructor); }}Copy the code

Injectable source code is simplified as follows:

// This is a class decorator
function injectable() {
  return function (target) {
    const metadataValue = []
    Reflect.defineMetadata('inversify:paramtypes', metadataValue, target)
    return target
  }
}
Copy the code

As you can see from the simplified source code, inject/ Injectable is ultimately a use of reflect.definemetadata (). Metadata can be thought of as a relatively efficient data structure.

reflect-metadata

InversityJS combines reflect-Metadata deeply, and reflect-Metadata extends its API on the basis of Reflect-Metadata.

Metadata is essentially a WeakMap object. Extension: Difference between Map and WeakMap

Reflect.definemetadata (metadataKey, metadataValue, Target [, propertyKey])

const Metadata = new WeakMap(a)function defineMetadata(metadataKey, metadataValue, target, propertyKey) {
  metadataMap = new Map()
  metadataMap.set(metadataKey, metadataValue)
  targetMetadata = new Map()
  targetMetadata.set(propertyKey, metadataMap)
  Metadata.set(target, targetMetadata)
}
Copy the code

Reflect.getownmetadata (metadataKey, target[, propertyKey]);

function getOwnMetadata(metadataKey, target, propertyKey) {
  var targetMetadata = Metadata.get(target)
  var metadataMap = targetMetadata.get(propertyKey)
  return metadataMap.get(metadataKey)
}
Copy the code

Its data structure can be expressed as follows:

WeakMap {
  target: Map {
    propertyKey: Map {
      metadataKey: metadataValue
    }
  }
}
Copy the code

A link to the

  • Architecture overview