import { Constructor } from "cc" type AbstractConstructor = abstract new (...args: any[]) => T; // enum Priority{ // DEFAULT, // } const Priority = { FRAMEWORK: 0, DEFAULT: 1, USER: 2 } // 打包之后有问题不支持名称注入 class SingletonAnnotation { private static TypeMap = new Map private static initNameMap = new Map() private static initTypeMap = new Map() private static typeSet = new Set /** *默认按类型注入, 如果填了类型或者名称,优先按填的name注入,只支持单例,不要填两个相同的name * @param name 名称注入|类型注入 * @param priority 权重 * @param consParam 构造函数的参数 * @returns */ static setSingleton(name?: string | Constructor | AbstractConstructor, priority: keyof (typeof Priority) = 'DEFAULT', ...consParam: any) { return function (target: any) { // 首字母小写注入 let priority1 = Priority[priority] consParam = consParam || [] let param = { target: target, consParam: consParam, priority: priority1 } if (!SingletonAnnotation.initTypeMap.has(target)) { SingletonAnnotation.initTypeMap.set(target, param); } // 使所有子类型的优先级最高 if (name) { if (typeof name == "string") { SingletonAnnotation.initNameMap.set(name, param); if (SingletonAnnotation.initNameMap.has(name)) { throw new Error("重复注入") } } else { if (SingletonAnnotation.typeSet.has(name)) { let data = SingletonAnnotation.initTypeMap.get(name) if (data.priority == priority1) { throw new Error("重复注入") } if (data.priority > priority1) { return } } SingletonAnnotation.typeSet.add(name) SingletonAnnotation.initTypeMap.set(name, param); } } } } private static create(target: Constructor, consParam: any[]) { if (SingletonAnnotation.TypeMap.has(target)) { return SingletonAnnotation.TypeMap.get(target) } let instance = new target(...consParam); SingletonAnnotation.TypeMap.set(target, instance); return instance } /** * 默认按属性名称注入 * @param name 名称构造器注入 * @returns */ static getSingleton(name?: Constructor | string | AbstractConstructor) { let res: PropertyDecorator = function (target, prop: string, desc?) { // 首字母小写注入 let value: any // 是否初始化 let init = false; return { get() { if (!init) { init = true if (!name) { name = prop } value = SingletonAnnotation.getValue(name) } return value }, set(v) { init = true; value = v }, } } return res } static getValue(name?: Constructor | string | AbstractConstructor) { if (!name) { return undefined; } let value if (typeof name != "string") { value = this.initObjByType(name); } else { value = this.initObjByName(name); } return value } private static initObjByName(name: string) { let v let param = SingletonAnnotation.initNameMap.get(name) if (param) { v = SingletonAnnotation.create(param.target, param.consParam) } return v } private static initObjByType(type: Constructor | AbstractConstructor) { // 首次创建类型需要重新对注入排序 let param = SingletonAnnotation.initTypeMap.get(type) if (param) { let v = SingletonAnnotation.create(param.target, param.consParam) return v } return null } } // export {SingletonAnnotation.setSingleton as t,SingletonAnnotation.getSingleton} const setSingleton = SingletonAnnotation.setSingleton const getSingleton = SingletonAnnotation.getSingleton export { setSingleton, getSingleton }