SingletonAnnotation.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { Constructor } from "cc"
  2. type AbstractConstructor<T = any> = abstract new (...args: any[]) => T;
  3. // enum Priority{
  4. // DEFAULT,
  5. // }
  6. const Priority = {
  7. FRAMEWORK: 0,
  8. DEFAULT: 1,
  9. USER: 2
  10. }
  11. // 打包之后有问题不支持名称注入
  12. class SingletonAnnotation {
  13. private static TypeMap = new Map
  14. private static initNameMap = new Map<string, { target: any, consParam: [] }>()
  15. private static initTypeMap = new Map<Constructor | AbstractConstructor, { target: Constructor, consParam: [], priority: number }>()
  16. private static typeSet = new Set<any>
  17. /**
  18. *默认按类型注入, 如果填了类型或者名称,优先按填的name注入,只支持单例,不要填两个相同的name
  19. * @param name 名称注入|类型注入
  20. * @param priority 权重
  21. * @param consParam 构造函数的参数
  22. * @returns
  23. */
  24. static setSingleton(name?: string | Constructor | AbstractConstructor, priority: keyof (typeof Priority) = 'DEFAULT', ...consParam: any) {
  25. return function (target: any) {
  26. // 首字母小写注入
  27. let priority1 = Priority[priority]
  28. consParam = consParam || []
  29. let param = { target: target, consParam: consParam, priority: priority1 }
  30. if (!SingletonAnnotation.initTypeMap.has(target)) {
  31. SingletonAnnotation.initTypeMap.set(target, param);
  32. }
  33. // 使所有子类型的优先级最高
  34. if (name) {
  35. if (typeof name == "string") {
  36. SingletonAnnotation.initNameMap.set(name, param);
  37. if (SingletonAnnotation.initNameMap.has(name)) {
  38. throw new Error("重复注入")
  39. }
  40. } else {
  41. if (SingletonAnnotation.typeSet.has(name)) {
  42. let data = SingletonAnnotation.initTypeMap.get(name)
  43. if (data.priority == priority1) {
  44. throw new Error("重复注入")
  45. }
  46. if (data.priority > priority1) {
  47. return
  48. }
  49. }
  50. SingletonAnnotation.typeSet.add(name)
  51. SingletonAnnotation.initTypeMap.set(name, param);
  52. }
  53. }
  54. }
  55. }
  56. private static create(target: Constructor, consParam: any[]) {
  57. if (SingletonAnnotation.TypeMap.has(target)) {
  58. return SingletonAnnotation.TypeMap.get(target)
  59. }
  60. let instance = new target(...consParam);
  61. SingletonAnnotation.TypeMap.set(target, instance);
  62. return instance
  63. }
  64. /**
  65. * 默认按属性名称注入
  66. * @param name 名称构造器注入
  67. * @returns
  68. */
  69. static getSingleton(name?: Constructor | string | AbstractConstructor) {
  70. let res: PropertyDecorator = function (target, prop: string, desc?) {
  71. // 首字母小写注入
  72. let value: any
  73. // 是否初始化
  74. let init = false;
  75. return {
  76. get() {
  77. if (!init) {
  78. init = true
  79. if (!name) {
  80. name = prop
  81. }
  82. value = SingletonAnnotation.getValue(name)
  83. }
  84. return value
  85. },
  86. set(v) { init = true; value = v },
  87. }
  88. }
  89. return res
  90. }
  91. static getValue(name?: Constructor | string | AbstractConstructor) {
  92. if (!name) {
  93. return undefined;
  94. }
  95. let value
  96. if (typeof name != "string") {
  97. value = this.initObjByType(name);
  98. } else {
  99. value = this.initObjByName(name);
  100. }
  101. return value
  102. }
  103. private static initObjByName(name: string) {
  104. let v
  105. let param = SingletonAnnotation.initNameMap.get(name)
  106. if (param) {
  107. v = SingletonAnnotation.create(param.target, param.consParam)
  108. }
  109. return v
  110. }
  111. private static initObjByType(type: Constructor | AbstractConstructor) {
  112. // 首次创建类型需要重新对注入排序
  113. let param = SingletonAnnotation.initTypeMap.get(type)
  114. if (param) {
  115. let v = SingletonAnnotation.create(param.target, param.consParam)
  116. return v
  117. }
  118. return null
  119. }
  120. }
  121. // export {SingletonAnnotation.setSingleton as t,SingletonAnnotation.getSingleton}
  122. const setSingleton = SingletonAnnotation.setSingleton
  123. const getSingleton = SingletonAnnotation.getSingleton
  124. export {
  125. setSingleton,
  126. getSingleton
  127. }