typescript实现一个最简的装饰器依赖注入

发布时间:2024年01月05日

装饰器依赖注入,元数据键是关键
因此必须开启ts装饰器和ts元数据

tsconfig.json

 "experimentalDecorators": true, // 开启装饰器
 "emitDecoratorMetadata": true, // 开启元数据

并且安装 reflect-metadata支持元数据编程
全局入口倒入一次即可

import "reflect-metadata";

类型元数据:使用元数据键 “design:type”(用来获取属性类型)
参数类型元数据:使用元数据键 “design:paramtypes”(用来获取参数类型)
返回值类型元数据:使用元数据键 “design:returntype”(用来获取返回值类型)

使用

Reflect.getMetadata('design:type', target, propertyKey); // 获取被装饰属性的类型
Reflect.getMetadata("design:paramtypes", target, propertyKey); // 获取被装饰的参数类型
Reflect.getMetadata("design:returntype", target, propertyKey); // 获取被装饰函数的返回值类型

一般 design:returntype用不上
design:type用来实现 多次注入 只创建一个实例
design:paramtypes用来获取构造函数的参数类型 去查找注入design:type依赖类

最小案例:
这个案例只是验证构造函数自动注入能力 没有使用到design:type

 const mockList = new MockList();
 console.log(mockList.getList(3))
type Constructable<T> = new (...args: any[]) => T;
/**
 * @description 将有参类转成无参类
 * 参数 自动注入
 */
function Injectable<T extends { new (...args: any[]): {} }>(target: T) {
   const constructorParams = Reflect.getMetadata("design:paramtypes", target);

    if (constructorParams.length) {
        return class extends target {
            constructor(...args: any[]) {
                const params: any[] = args.concat(
                    constructorParams.map((paramType: Constructable<any>) => {
                        return new paramType();
                    })
                );
                super(...params);
            }
        };
    }
    return target;
}
class Random {
    color() {
        return `#${Math.floor(Math.random() * 0xffffff)
            .toString(16)
            .padEnd(6, (Math.random() * 0xf).toString(16)[0])}`;
    }
}

@Injectable
class MockList {
    constructor(private random?: Random) {}

    getList(count: number) {
        return Array.from(new Array(count)).map((_, index) => ({
            color: this.random?.color() ?? "woc",
            index,
        }));
    }
}

在这里插入图片描述

文章来源:https://blog.csdn.net/printf_hello/article/details/135388255
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。