用reflect-metadata实现简单依赖注入!
import "reflect-metadata";
import { Type } from '../type';
const ListMetadata = '__list_metadata_';
// 缓存
const listCache: Map<Type<any>, any> = new Map();
// 错误
export class ListError extends Error {
constructor(msg: string, public type: Type<any>) {
super(msg);
}
}
// 依赖注入工厂
class InjectorFactory {
private _list: Type<any>[] = [];
constructor(private type: Type<any>, ...args: Type<any>[]) {
this._list = args;
}
create() {
const params = [];
for (let li of this._list) {
const _li = Reflect.getMetadata(ListMetadata, li);
if (_li) {
params.push(_li.create());
} else {
throw new ListError('Reflect metadata empty', this.type);
}
}
return new this.type(...params);
}
}
// 装饰器
export function injector(...args: Type<any>[]) {
return (target: any) => {
Reflect.defineMetadata(ListMetadata, new InjectorFactory(target, ...args), target);
}
}
export abstract class IInjector {
abstract get(key: Type<any>): any;
}
// 静态依赖注入
export class StaticInjector {
static get(key: Type<any>) {
if (listCache.has(key)) {
return listCache.get(key);
} else {
try {
const list = Reflect.getMetadata(ListMetadata, key).create();
listCache.set(key, list);
return list;
} catch (err) {
throw new ListError('创建失败', key);
}
}
}
}
// 多级依赖注入
export class Injector extends IInjector {
_list: Map<Type<any>, any> = new Map();
constructor(private parent?: IInjector) {
super();
this.parent = this.parent || { get: StaticInjector.get } as IInjector;
}
get(key: Type<any>, _default?: any) {
if (this._list.has(key)) {
return this._list.get(key)
} else {
let inject = this.parent.get(key);
if (!inject) {
inject = _default;
}
this._list.set(key, inject);
return inject;
}
}
}
复制代码
使用
@Injector()
class B{
constructor(){}
}
@Injector(B)
class A{
constructor(public b: B){}
}
@Injector(B,A)
class C{
constructor(
public b: B,
public a: A
){}
}
StaticInjector.get(C)
复制代码
改进
import { Record, DependencyRecord, OptionFlags } from './injector';
import { IFunction } from '../../../functor';
export type IResolveRecord = IFunction<Record, any>;
export type IResolveRecordWithRecordMap = IFunction<Map<any, Record>, IResolveRecord>;
export type IResolveDep = IFunction<DependencyRecord, any>;
export type IResolveDepWithRecordMap = IFunction<Map<any, Record>, IResolveDep>;
export type IResolveToken = (token: any) => any;
export const resolveToken = (recordMap: Map<any, Record>) => {
return (token: any) => {
const record = recordMap.get(token);
return resolveRecord(recordMap)(record)
}
}
export const resolveDepRecord: IResolveDepWithRecordMap = (recordMap: Map<any, Record>) => {
return (dep: DependencyRecord) => {
const record = dep.options & OptionFlags.CheckSelf ? recordMap.get(dep.token) : undefined;
return resolveRecord(recordMap)(record)
}
}
export const resolveRecord: IResolveRecordWithRecordMap = (recordMap: Map<any, Record>) => {
return (record: Record) => {
// 相当于缓存
if (record.value) {
return record.value;
}
let deps = [];
if (Array.isArray(record.deps) && record.deps.length > 0) {
deps = record.deps.map(dep =>
resolveDepRecord(recordMap)(dep)
)
}
if (record.useNew) {
return record.value = new (record.fn as any)(...deps)
} else if (record.fn) {
return record.value = (record.fn as any)(...record.deps)
}
}
}
复制代码