@bylive/ioc
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

ioc-typescript

一个高效轻量级的 ioc 控制反转和DI 依赖注入的typescript 库

基本使用 ContainerBase

// import {ContainerBase,Injectable} from "../index"
import {ContainerBase,Injectable} from "ioc-typescript"


@Injectable()
class A{
    
    getA(){
       
        console.log("class A method getA")
    }
}

@Injectable()
class B{
    constructor(private a:A){}
    getB(){
        this.a.getA()
        console.log("class B method getB")
    }
}

const containerIns = new ContainerBase()
containerIns.addProviders<any>([A,B]).initLoading()

let ins = containerIns.getInstances()
ins.forEach((val,key)=>{
    console.log("get-ins",key,val) ; // log 输出: get-ins [class A] A {}, get-ins [class B] B { a: A {} }
})
const insB:B = ins.get(B)
insB.getB() ; // log 输出:class A method getA,  class B method getB

示例二 :Container 与 Module

// import {Container,Injectable, Module} from "../index"
import {Container,Injectable, Module} from "ioc-typescript"


@Injectable()
class A{
    
    getA(){
       
        console.log("class A method getA")
    }
}

@Injectable()
class B{
    constructor(private a:A){}
    getB(){
        this.a.getA()
        console.log("class B method getB")
    }
}

@Module({
    providers:[A],
    controllers:[], // 这个特殊是providers 
    imports:[]
})
class Ma{}


@Module({
    providers:[B],
    imports:[Ma]
})
class Mb{}

const containerIns = new Container(Mb)
let ins = containerIns.getInstances()
ins.forEach((val,key)=>{
    /** log 输出:
     *  get-ins [class Mb] Mb {}
        get-ins [class B] B { a: A {} }
        get-ins [class Ma] Ma {}
        get-ins [class A] A {}
     */
    console.log("get-ins",key,val) ; 
})
const insB:B = ins.get(B)
/** log 输出:
 *  class A method getA
 *  class B method getB
 */
insB.getB() ; 

示例三: 循环依赖forwardRef

  • A类实例化的时候依赖B类 ,B类的实例化的时候依赖A类 ,这样就造成了依赖循环
  • 注意: 不能 A 类的a 方法里面调用B 类的 a 方法,然后B 类的 a 方法 又调用了A 类的a 方法 ,这种就是死循环,无解

src/depA.ts

// import { Injectable ,Inject,forwardRef} from "../../index";
import { Injectable ,Inject,forwardRef} from "ioc-typescript";
import { B } from "./depB";


@Injectable()
export class A {
  constructor(@Inject(forwardRef(()=>B)) private b:B){}
  getA() {
    this.b.getA()
    console.log("class A methond getA");
  }

  getB() {
    console.log("class A methond getB");
  }
}

src/depB.ts

// import { Injectable ,Inject,forwardRef} from "../../index";
import { Injectable ,Inject,forwardRef} from "ioc-typescript";
import { A } from "./depA";


@Injectable()
export class B {
  constructor(@Inject(forwardRef(()=>A)) private a:A){}
  getA() {
    console.log("class B methond getA");
  }
  getB() {
    this.a.getB()
    console.log("class B methond getB");
  }
}

src/index.ts

// import {Container,forwardRef, Module} from "../../index"
import {Container,Injectable, Module} from "ioc-typescript"
import {A} from "./depA"
import {B} from "./depB"


@Module({
    providers:[forwardRef(()=>A),forwardRef(()=>B)],
    imports:[]
})
class M{}

const containerIns = new Container(M)
let ins = containerIns.getInstances()
ins.forEach((val,key)=>{
    /** log 输出:
      get-ins [class M] M {}
      get-ins [class A] <ref *1> A { b: B { a: [Circular *1] } }
      get-ins [class B] <ref *1> B { a: A { b: [Circular *1] } }
     */
    console.log("get-ins",key,val) ; 
})


/** log 输出:
*  class B methond getA
*  class A methond getA
*/
const insA:A = ins.get(A)
insA.getA() ;



/** log 输出:
 * class A methond getB
 * class B methond getB
 */
const insB:B = ins.get(B)
insB.getB() ;

示例4 ,三种绑定用法

  • 类绑定:{ provide, useClass},
  • 工厂方法绑定: { provide,useFactory}
  • 值绑定: { provide,useValue}
// import {Inject,InjectToken,Injectable,forwardRef,Container,Module} from "../index"
import {Inject,InjectToken,Injectable,forwardRef,Container,Module} from "ioc-typescript"


 const APP_URL = new InjectToken("APP_URL")

@Injectable()
class A{

    getA(){

        console.log("class A method getA")
    }
}

@Injectable()
class B{
    constructor(private a:A){}
    getB(){
        this.a.getA()
        console.log("class B method getB")
    }
}

@Injectable()
export class C{
    constructor(
        @Inject(APP_URL) private appUrl:string
    ){
        console.log(this.appUrl,"C int----------")
    }
}


@Module({
    providers: [
        A,
        {provide:B,useClass:B},
        {provide:C,useClass:forwardRef(()=>C)},
        {
        provide: APP_URL,
            useFactory: () => "http://www.baidu.com",
        },
        {provide:"useValue",useValue:"this is useValue"},
        {provide:"useFactory",useFactory:()=>"this is useFactory"},
        {provide:"config",useValue:()=>({  id:12 })}
    ],
    controllers: [],
  })
  class userApp {
    constructor() {
      console.log("userApp init....");
    }
  }



  const containerIns = new Container(userApp);
  let ins = containerIns.getInstances()

  ins.forEach((val,key)=>{
     /**
      * log 输出:
      * userApp init....
        http://www.baidu.com C int----------
        get-ins key:---: [class userApp] ----val---: userApp {}
        get-ins key:---: [class A] ----val---: A {}
        get-ins key:---: [class B] ----val---: B { a: A {} }
        get-ins key:---: InjectToken { injectIdefer: 'APP_URL' } ----val---: http://www.baidu.com
        get-ins key:---: useValue ----val---: this is useValue
        get-ins key:---: useFactory ----val---: this is useFactory
        get-ins key:---: config ----val---: [Function: useValue]
        get-ins key:---: [class C] ----val---: C { appUrl: 'http://www.baidu.com' }
      */
      console.log("get-ins","key:---:",key,"----val---:",val)
  })

APi 参数说明

一、 提供两个容器,ContainerBase 与 Container ,Container 是增强版继承与ContainerBase, 与@Module 结合使用


1、ContainerBase: 构造函数参数:无 实例方法有:

  • getInstances(): 获取所有容器已经注册的服务

  • addProvider(provider:Type | Provider | IforwardRef): 单个添加已经被注解的类,或者工厂函数,值

  • addProviders(providers:Array<Type | Provider | IforwardRef>): 批量添加已经被注解的类,或者工厂函数,值

  • bind(provider:Provider): 单个绑定注入,约定三种结构:{provide:"",useClass:}、{provide:"",useFactory:} 、 {provide:"",useValue:}

  • initLoading():初始化所有提供者服务Provider

  • get(type: Token): 根据 provide 获取注入的服务

2、Container : 构造函数参数: 接受一个参数 使用@module 注入的服务 实例方法: 继承ContainerBase

二、 提供三个注解方法 @Inject、@Injectable 、@Module


装饰器方法 描述
@Inject 构造函数参数的注入器
@Injectable 标志可注入依赖
@Module 标志可注入依赖的模块,接受一个参数对象 {providers,controllers,imports}

三、forwardRef:标志这是一个依赖循环的服务,接受一个函数,返回 一个provider


四、InjectToken:是一个构造类,用于生成一个 可以注入的provider服务


Package Sidebar

Install

npm i @bylive/ioc

Weekly Downloads

0

Version

1.0.0

License

ISC

Unpacked Size

34.5 kB

Total Files

22

Last publish

Collaborators

  • beyonds