文章目录

  • 一、简介
  • 二、InversifyJS 为何而生 ?
  • 三、目标
  • 四、安装
  • 五、应用示例
    • 步骤 1: 声明接口和类型
    • 步骤 2: 使用 @injectable 和 @inject 装饰器声明依赖
    • 步骤 3: 创建和配置容器
    • 步骤 4: 解析依赖
  • 六、拓展阅读

一、简介

InversifyJS ,一个强大又轻量的控制反转容器,提供给JavaScriptNode.js 应用使用,使用TypeScript编写。

InversifyJS 是一个轻量的 (4KB) 控制反转容器 (IoC),可用于编写 TypeScriptJavaScript 应用。 它使用类构造函数去定义和注入它的依赖。InversifyJS API 友好易懂, 是鼓励对 OOPIoC 最佳实践的应用.

二、InversifyJS 为何而生 ?

JavaScript 现在支持面向对象编程,基于类的继承。 这些特性不错但事实上它们也是危险的。 我们需要一个优秀的面向对象设计(比如 SOLIDComposite Reuse等)来保护我们避免这些威胁。然而,面向对象的设计是复杂的,所以InversifyJS应运而生。

InversifyJS 是一个工具,它能帮助 JavaScript 开发者,写出出色的面向对象设计的代码。

三、目标

InversifyJS有4个主要目标:

  • 允许JavaScript开发人员编写遵循 SOLID 原则的代码。

  • 促进并鼓励遵守最佳的面向对象编程(OOP)和依赖注入(IoC)实践。

  • 尽可能少的运行时开销。

  • 提供艺术编程体验和生态。

四、安装

可以使用npm获得最新的版本和类型定义:

$ npm install inversify reflect-metadata --save

注:由于 InversifyJS 通过反射来获取装饰器的相关元数据,所以需要额外安装库 reflect-metadata

Inversify npm 包已经包含了 InversifyJS 的类型定义。

:警示⚠️: InversifyJS 需要 TypeScript 版本 >= 2.0 还有experimentalDecorators, emitDecoratorMetadata, types and libtsconfig.jsoncompilerOptions 的配置如下:

{"compilerOptions": {"target": "es5","lib": ["es6"],"types": ["reflect-metadata"],"module": "commonjs","moduleResolution": "node","experimentalDecorators": true,"emitDecoratorMetadata": true}
}

inversifyjs需要现代JavaScript引擎,支持以下特性:

  • Reflect metadata
  • Map
  • Promise (Only required if using provider injection)
  • Proxy (Only required if using activation handlers)

如果运行环境不支持这些特性,可能需要导入 shimpolyfill.

:警示⚠️: reflect-metadata polyfill 应该在整个应用中只导入一次, 因为 Reflect 对象需要成为一个全局的单例。

五、应用示例

inversifyjs 基本用法和 API应用示例如下:

步骤 1: 声明接口和类型

目标是编写遵循依赖倒置原则的代码。

这意味着我们应该 ”依赖于抽象而不依赖于具体实现“ 。

先声明一些接口(抽象)。

// file interfaces.tsinterface Warrior {fight(): string;sneak(): string;
}interface Weapon {hit(): string;
}interface ThrowableWeapon {throw(): string;
}

Inversifyjs 需要在运行时使用类型标记作为标识符。接下来将使用 Symbol 作为标识符,也可以使用类或字符串。

// file types.tsconst TYPES = {Warrior: Symbol.for("Warrior"),Weapon: Symbol.for("Weapon"),ThrowableWeapon: Symbol.for("ThrowableWeapon")
};export { TYPES };

警示⚠️: 推荐使用 Symbol,但 InversifyJS 也支持使用类和字符串字面值。

步骤 2: 使用 @injectable 和 @inject 装饰器声明依赖

接下来,声明一些类,实现刚刚声明的接口。需要使用 @injectable 装饰器去注解。

当一个类依赖于某个接口时,需要使用 @inject 装饰器,来定义在运行时可用的接口标识。在这种情况下,将使用 Symbol, 如 Symbol.for("Weapon")Symbol.for("ThrowableWeapon") 作为运行时的标识。

// file entities.tsimport { injectable, inject } from "inversify";
import "reflect-metadata";
import { Weapon, ThrowableWeapon, Warrior } from "./interfaces"
import { TYPES } from "./types";@injectable()
class Katana implements Weapon {public hit() {return "cut!";}
}@injectable()
class Shuriken implements ThrowableWeapon {public throw() {return "hit!";}
}@injectable()
class Ninja implements Warrior {private _katana: Weapon;private _shuriken: ThrowableWeapon;public constructor(@inject(TYPES.Weapon) katana: Weapon,@inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon) {this._katana = katana;this._shuriken = shuriken;}public fight() { return this._katana.hit(); }public sneak() { return this._shuriken.throw(); }}export { Ninja, Katana, Shuriken };

如果更喜欢使用属性注入而不是构造函数注入,那就可以不用声明类的构造函数了,属性注入方式如下:

@injectable()
class Ninja implements Warrior {@inject(TYPES.Weapon) private _katana: Weapon;@inject(TYPES.ThrowableWeapon) private _shuriken: ThrowableWeapon;public fight() { return this._katana.hit(); }public sneak() { return this._shuriken.throw(); }
}

步骤 3: 创建和配置容器

推荐在命名为 inversify.config.ts 的文件中创建和配置容器。这是唯一有耦合的地方。 在项目其余部分中的类,不应该包含对其他类的引用。

// file inversify.config.tsimport { Container } from "inversify";
import { TYPES } from "./types";
import { Warrior, Weapon, ThrowableWeapon } from "./interfaces";
import { Ninja, Katana, Shuriken } from "./entities";const myContainer = new Container();
myContainer.bind<Warrior>(TYPES.Warrior).to(Ninja);
myContainer.bind<Weapon>(TYPES.Weapon).to(Katana);
myContainer.bind<ThrowableWeapon>(TYPES.ThrowableWeapon).to(Shuriken);export { myContainer };

步骤 4: 解析依赖

可以使用方法 get<T>Container 中获得依赖。记得应该在项目根结构(尽可能靠近应用程序的入口点的位置)去解析依赖,避免服务器定位反模式。

import { myContainer } from "./inversify.config";
import { TYPES } from "./types";
import { Warrior } from "./interfaces";const ninja = myContainer.get<Warrior>(TYPES.Warrior);expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true

正如我们所看到的,Katana and Shuriken 被成功的解析和注入进 Ninja。

InversifyJS 支持 ES5ES6 ,而且可以在没有 TypeScript 环境下使用。

不做知识的搬运工,只做知识的汇聚者!

注:本文节选自https://doc.inversify.cloud/zh_cn/,学习InversifyJS,看此文足矣!!墙裂推荐!!

六、拓展阅读

  • InversifyJS【Github】
  • 中文文档
  • 《ReactNative进阶(二十八):ES6 Symbol 用法》

ReactNative进阶(三十一): IoC 框架 InversifyJS 解读相关推荐

  1. Python爬虫进阶三之Scrapy框架安装配置

    初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此整理如下. Windows 平台: 我的系统是 ...

  2. Python 爬虫进阶三之 Scrapy 框架安装配置

    初级的爬虫我们利用 urllib 和 urllib2 库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架 Scrapy,这安装过程也是煞费苦心哪,在此整理如下. 官网 官方安装文档 安装p ...

  3. python爬虫架构设置_Python爬虫进阶三之Scrapy框架安装配置

    初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此整理如下. Windows 平台: 我的系统是 ...

  4. ReactNative进阶(三十五):应用脚手架 Yo 构建 RN 页面

    文章目录 一.前言 二.Bloc 数据流讲解 三.利用代码自动生成功能创建新页面 四.Bloc数据流使用说明 五.拓展阅读 一.前言 前期将脚手架yo安装成功,本篇博文主要讲解如何利用yo提供的代码自 ...

  5. 【FastDev4Android框架开发】RecyclerView完全解析之下拉刷新与上拉加载SwipeRefreshLayout(三十一)...

    转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息] ...

  6. Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)

    上一篇博客我们已经带大家简单的吹了一下IoC,实现了Activity中View的布局以及控件的注入,如果你不了解,请参考:Android 进阶 教你打造 Android 中的 IOC 框架 [View ...

  7. Android进阶:框架打造之IOC框架

    什么是IOC IOC(Inversion of Control):控制反转.开发过程中类里面需要用到很多个成员变量 传统的写法:你要用这些成员变量的时候,那么你就new出来用 IOC的写法:你要用这些 ...

  8. PhotoShop算法实现进阶-浮雕滤镜-灰度浮雕(三十一)

    PhotoShop算法实现进阶-浮雕滤镜-灰度浮雕(三十一) kezunhai@gmail.com http://blog.csdn.net/kezunhai 浮雕效果可谓花样百出,但他们主要是基于图 ...

  9. ReactNative进阶(四十一):应用 FlatList 实现分组列表

    一.功能简介 二.属性说明 三.方法集合 四.简单应用示例 五.高阶应用示例 六.拓展阅读 一.功能简介 FlatList为高性能的简单列表组件,支持下面这些常用的功能: 完全跨平台. 支持水平布局模 ...

最新文章

  1. 苹果手机微信上form表单提交的问题
  2. Java深度历险:Java注解
  3. li:hover背景色
  4. 云架构的基础转变会带来哪些变化?
  5. ubuntu19.10安装remarkable
  6. 机器学习——决策树的实现
  7. Java 故障处理与性能监控工具
  8. 虚拟专题:知识图谱 | 事件图谱的构建、推理与应用
  9. 作者:杨燕(1964-),女,西南交通大学信息科学与技术学院教授、博士生导师。...
  10. 读书笔记--云边有个小卖部
  11. (补)20200105:整数转罗马数字
  12. 3个人的java 实验_20165104-JAVA第三次实验
  13. java8时间类的好处_Java8——时间类
  14. python爬虫数据分析案例-Python 爬虫和数据分析实战
  15. 如何使用WordPress美化网站
  16. linux下声卡配置文件,Linux如何设置声卡
  17. 二进制加法器原理c语言,加法器电路原理_二进制加法器原理_与非门二进制加法器...
  18. swoole php配置文件,EasySwoole分离配置文件
  19. php文件转换为mp4,PHP转换视频为MP4并获取预览图的实例分享
  20. 判别机器大小端,打印int的二进制

热门文章

  1. 破解TCP为Windows7下的迅雷提速(图形方式修改)
  2. bootload启动流程(三)--Eboot每个函数的详细说明
  3. 谷歌收购边缘云初创企业MobiledgeX
  4. 复函数积分的共轭等于其共轭的积分
  5. Windows 编程中的数据类型(转自:维基百科)
  6. 如何封禁大量恶意 IP
  7. 日媒感慨中国手机发展,超乎日本人想象!
  8. Hive学习—数据操作
  9. CodeForces 597A
  10. CF597 (Div. 2)题解