Gathering detailed insights and metrics for mana-syringe
Gathering detailed insights and metrics for mana-syringe
Gathering detailed insights and metrics for mana-syringe
Gathering detailed insights and metrics for mana-syringe
npm install mana-syringe
Typescript
Module System
Node Version
NPM Version
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
IoC library for mana, easily to use.
提供易于使用的依赖注入容器,参考 TSyringe 项目,参考并基于 inversify。
1npm i mana-syringe --save
注入绑定对象所使用的的标识,可以带有一定的类型约束
1Token<T> = string | symbol | Newable<T> | Abstract<T> | Syringe.DefinedToken<T>;
除 Syringe.DefinedToken<T>
默认支持多绑定外,注入标识只支持单一绑定关系。可以使用如下 API 生成 DefinedToken
1Syringe.defineToken('sample-token');
包含一组绑定标识与注入对象关系描述的上下文成为容器,当我们通过容器获取实例时,容器会根据注入对象及其与标识的关系自动构建所需的其他实例。
用户可以手动创建容器,使用全局默认的容器,或者创建子容器
1import { GlobalContainer, Container } from './container'; 2const global = GlobalContainer; 3const container = new Container(); 4const child = container.createChild();
我们使用 token
从容器里获取对象
1const ninja = child.get(Ninja);
当我们从子容器中获取对象时,会先从子容器查找绑定关系和缓存信息,如果不存在,则继续向父容器查找。
容器上暴露了 register 方法,这个 API 是整个体系的核心。 register 方法有两种签名
1register<T = any>(options: Syringe.InjectOption<T>): void; 2register<T = any>(token: Syringe.Token<T>, options?: Syringe.InjectOption<T>): void;
可以调用容器实例上的 register 方法,也可以直接调用全局的 register 方法,其相对于调用 GlobalContainer 的方法。
从签名可以看出,注册绑定需要一组配置,在不同场景下配置会有所不同,可能出现的配置项如下
1interface { 2 token?: MaybeArray<UnionToken<T>>; 3 contrib?: MaybeArray<Token<T>>; 4 lifecycle?: Lifecycle; 5 useClass?: MaybeArray<Class<T>>; 6 useDynamic?: MaybeArray<Dynamic<T>>; 7 useFactory?: MaybeArray<Factory<T>>; 8 useValue?: T; 9}
容器会根据注入对象的生命期描述托管这些对象,决定是否使用缓存等。
1export enum Lifecycle { 2 singleton = 'singleton', 3 transient = 'transient', 4}
1@singleton({ contrib: Alias }) 2class Shuriken implements Weapon { 3 public hit() { 4 console.log('Shuriken hit'); 5 } 6} 7GlobalContainer.register(Shuriken); 8GlobalContainer.register(Shuriken, { 9 useClass: Shuriken, 10 lifecycle: Syringe.Lifecycle.singleton, 11});
通过 token 注册后,每个 token 的注册关系是独立的,通过他们获取对象可以是不同的值,通过 contrib 注册的是别名关系,他们应该获取到同一个对象。不管是 token 还是 contrib,根据对多绑定的支持情况做处理。
1const Weapon = Symbol('Weapon'); 2const WeaponArray = Syringe.defineToken('Weapon'); 3@singleton({ contrib: Weapon }) 4class Shuriken implements Weapon { 5 public hit() { 6 console.log('Shuriken hit'); 7 } 8} 9GlobalContainer.register({ token: Weapon, useValue: undefined }); 10GlobalContainer.register({ token: WeaponArray, useValue: undefined }); 11GlobalContainer.register(Shuriken); 12GlobalContainer.get(Weapon); // Shuriken 13GlobalContainer.getAll(WeaponArray); // [undefined, Shuriken]
1const ConstantValue = Symbol('ConstantValue'); 2GlobalContainer.register({ token: ConstantValue, useValue: {} });
1const NinjaAlias = Symbol('NinjaAlias'); 2GlobalContainer.register({ 3 token: NinjaAlias, 4 useDynamic: ctx => ctx.container.get(Ninja), 5});
我们提供了一组对类与属性的装饰器函数,用来快速完成基于依赖注入的类型描述,并完成基本的绑定关系描述。
1@singleton() 2class Shuriken implements Weapon { 3 public hit() { 4 console.log('Shuriken hit'); 5 } 6} 7@transient() 8class Ninja { 9 @inject(Weapon) public weapon: Weapon; 10 public hit() { 11 this.weapon.hit(); 12 } 13}
我们通常将依赖注入的多绑定模式以扩展点的形式使用,为了方便在项目中使用这种模式,我们内置了对扩展点的定义和支持。
1const Weapon = Syringe.defineToken('Weapon'); 2Contribution.register(GlobalContainer.register, Weapon);
内置了扩展点的管理服务,用户一般直接使用即可,注册扩展点以后,通过如下方式获取扩展服务
1@contrib(Weapon) public weaponProvider: Contribution.Provider<Weapon>;
等价于如下写法
1@inject(Contribution.Provider) @named(Weapon) public weaponProvider: Contribution.Provider<Weapon>; 2
1const Weapon = Syringe.defineToken('Weapon'); 2Contribution.register(GlobalContainer.register, Weapon); 3@singleton({ contrib: Weapon }) 4class Shuriken implements Weapon { 5 public hit() { 6 console.log('Shuriken hit'); 7 } 8} 9@transient() 10class Ninja { 11 @contrib(Weapon) public weaponProvider: Contribution.Provider<Weapon>; 12 hit() { 13 const weapons = this.weaponProvider.getContributions(); 14 weapons.forEach(w => w.hit()); 15 } 16} 17const module = Module(register => { 18 Contribution.register(register, Weapon); 19 register(Shuriken); 20 register(Ninja); 21}); 22GlobalContainer.register(Shuriken); 23GlobalContainer.register(Ninja); 24GlobalContainer.get(Ninja).hit(); // Shuriken hit
可以通过用一组注册动作创建一个模块,方便在不同容器上下文间内加载, 模块的构建支持注册函数和链式调用两种方式,前面扩展点示例里的模块也可以写成如下形式:
1const module = Module().contribution(Weapon).register(Shuriken, Ninja); 2 3GlobalContainer.load(module);
No vulnerabilities found.
No security vulnerabilities found.