50行代码简单实现依赖注入

本文介绍如何使用 reflect-metadata 库来实现简单的依赖注入。通过定义装饰器和依赖注入工厂,可以有效地管理类之间的依赖关系,并展示了静态依赖注入和多级依赖注入的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用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)
        }
    }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值