使用Typescript实现依赖注入(DI)
2018-04-01 10:26
851 查看
使用Typescript实现依赖注入(DI)
前言
DI总是和ico相辅相成的,如果想对DI有更多的了解,可以移步我的另一篇文章 依赖注入(DI)和控制反转(IOC),再次我就不多做赘述了。前几天看见一道面试题,今天借这个话题想跟大家分享一下:
为什么在实际开发中,我们总是用DI,而不是用工厂模式,工厂模式也能实现同样的效果
emmmm,想了一下,DI相当于是一种把当前对象和它所依赖的对象强解耦了,注入对象并不需要我们操心,而是把它委托给第三方,这个第三方可以是一些库或者框架,也可以是我们自己实现的ioc容器。而工厂模式,它是可以把我们需要的对象放进去,然后产生出我们最终需要的实例,但是创建这部分过程实际上还是由我们来做了。
Typescript依赖注入
javascript的动态类型,有时候会给我们带来很多的麻烦,实际上如果js能够在编译期就识别类型,那么性能会大大提升,比如webassembly。typescript不一样,它是js的超集,它始终会先用tsc编译一遍,再转换为js运行,它始终是js,但是ts在编译期就检查类型,是可以让我们避免很多的错误的。如果想了解更多typescript请移步ts官网
typescript被很多框架所采用,比如angular,并且以它实现了依赖注入,我们在angular中,将一个类注册进ioc容器,只需给它附加一个injectable装饰器即可,比如:
@Injectable() class User{ //... }
在angular中,我们把用injectable装饰器修饰的类叫做service,我们可以在任何我们需要User类的时候,注入进来,比如:
class Main{ constructor(priavte user:User){ } }
只需在构造函数的参数上写上对user的依赖,那么ioc容器就会帮助我们把user注入进来。
实现一个精简的DI
其实DI的具体实现并不是很复杂,现在我们来实现一个精简版的DI。核心思想:根据类所声明的依赖,判断该依赖是否处于ioc容器中,如果处于,将它注入,并返回该类的实例,如果不属于,抛出一个异常,通知必须将依赖进行注册。
大致分为两部分:
1.注册
2.创建实例
先看看如何使用,再说具体实现
假如现在有A,B,C三个类
@Injectable() class C{ constructor(){} } @Injectable() class B{ constructor(private c:C){ } } @Injectable() class A{ constructor(priavte b:B){} } //产生实例 let a:A = classFactory(A);
在A中声明对B的依赖,在B中声明对C的依赖。
每个类都用injectable装饰器进行装饰,实际上是把它们放进了ioc容器。
通过classFactory返回A的实例,此时b已经被注入进来了,同时c也已经注入进b,classFactory完成注入的动作。
下面看一下具体实现:
目录树
src |-- index.ts |-- ioc.ts
ioc.ts
//ioc容器 let classPool:Array<Function> = []; //注册该类进入容器 export function Injectable(){ return (_constructor:Function) => { let paramTypes:Array<Function> = Reflect.getMetadata('design:paramtypes',_constructor) //已注册 if(classPool.indexOf(_constructor) != -1) return; for(let val of paramTypes){ if(val === _constructor) throw new Error('不能依赖自己') else if(classPool.indexOf(val) == -1) throw new Error(`${val}没有被注册`) } //注册 classPool.push(_constructor); } } //实例化工厂 export function classFactory<T>(_constructor:{new(...args:Array<any>):T}):T{ let paramTypes:Array<Function> = Reflect.getMetadata('design:paramtypes',_constructor) //参数实例化 let paramInstance = paramTypes.map((val:Function) => { //依赖的类必须全部进行注册 if(classPool.indexOf(val) == -1) throw new Error(`${val}没有被注册`) //参数还有依赖 else if(val.length){ return classFactory(val as any); } //没有依赖直接创建实例 else{ return new (val as any)(); } }) return new _constructor(...paramInstance); }
index.ts
@Injectable() class C{ constructor(){} } @Injectable() class B{ constructor(private c:C){ } } @Injectable() class A{ constructor(priavte b:B){} } //产生实例 let a:A = classFactory(A);
为了验证DI的有效性,可以为C声明一个实例方法,比如
@Injectable() class C{ constructor(){} sayHello(){ console.log("hello") } } @Injectable() class B{ constructor(private c:C){ } sayHello(){ this.c.sayHello(); } } @Injectable() class A{ constructor(priavte b:B){ b.sayHello(); } } //产生实例 let a:A = classFactory(A);
运行后
hello
参考:https://zhuanlan.zhihu.com/p/22962797
相关文章推荐
- ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下
- ASP.Net MVC3 使用Unity实现依赖注入介绍
- 扩展ASP.NET MVC三层框架且使用StructureMap实现依赖注入1-Model层
- .NET中使用Unity和StructureMap来实现依赖注入Dependency Injection
- 扩展ASP.NET MVC三层框架并使用StructureMap实现依赖注入1-Model层的实现
- NopCommerce是如何使用Autofac实现依赖注入的
- 系统学习MVC3搭建网站(4)--利用NuGet安装Ninject.MVC3实现依赖注入(DI)
- 使用Unity.Mvc3实现依赖注入简介
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【四】——实现模型工厂,依赖注入以及格式配置
- 扩展ASP.NET MVC三层框架并使用StructureMap实现依赖注入1
- 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【四】——实现模型工厂,依赖注入以及格式配置
- ASP.NET MVC3使用Unity2.0实现依赖注入
- seasar2中使用ognl实现依赖注入
- 扩展ASP.NET MVC三层框架并使用StructureMap实现依赖注入2-Repository层的实现
- 使用spring的aop实现权限拦截后出现依赖注入为空的问题
- 使用BeanPostProcessor实现依赖注入的修正器
- 使用Unity 实现依赖注入
- WCF Rest Service使用Unity实现依赖注入
- <收录>使用Ninject实现依赖注入(控制反转)
- MVC3使用Unity实现依赖注入接口与于实现类自动注册