فهرست منبع

Initializable decorator refactoring: Reflect-metadata

sanex3339 7 سال پیش
والد
کامیت
e44c160286
3فایلهای تغییر یافته به همراه47 افزوده شده و 11 حذف شده
  1. 0 0
      dist/index.js
  2. 45 11
      src/decorators/Initializable.ts
  3. 2 0
      src/storages/custom-node-group/CustomNodeGroupStorage.ts

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/index.js


+ 45 - 11
src/decorators/Initializable.ts

@@ -8,6 +8,7 @@ const defaultDescriptor: PropertyDescriptor = {
 };
 const initializedTargetMetadataKey: string = '_initialized';
 const initializablePropertiesSetMetadataKey: string = '_initializablePropertiesSet';
+const wrappedMethodsSetMetadataKey: string = '_wrappedMethodsSet';
 const constructorMethodName: string = 'constructor';
 
 /**
@@ -27,17 +28,39 @@ export function initializable (
                 `found. \`@${decoratorName}\` decorator requires \`${initializeMethodName}\` method`);
         }
 
-        if (!target[initializablePropertiesSetMetadataKey]) {
-            target[initializablePropertiesSetMetadataKey] = new Set();
-        }
+        /**
+         * Stage #1: initialize target metadata
+         */
+        initializeTargetMetadata(initializedTargetMetadataKey, false, target);
+        initializeTargetMetadata(initializablePropertiesSetMetadataKey, new Set(), target);
+        initializeTargetMetadata(wrappedMethodsSetMetadataKey, new Set(), target);
 
+        /**
+         * Stage #2: wrap target methods
+         */
         wrapTargetMethodsInInitializedCheck(target, initializeMethodName);
         wrapInitializeMethodInInitializeCheck(target, initializeMethodName, propertyKey);
 
+        /**
+         * Stage #3: wrap target properties
+         */
         return wrapInitializableProperty(target, propertyKey);
     };
 }
 
+/**
+ * @param {string} metadataKey
+ * @param metadataValue
+ * @param {IInitializable} target
+ */
+function initializeTargetMetadata (metadataKey: string, metadataValue: any, target: IInitializable, ): void {
+    const hasInitializedMetadata: boolean = Reflect.hasMetadata(metadataKey, target);
+
+    if (!hasInitializedMetadata) {
+        Reflect.defineMetadata(metadataKey, metadataValue, target);
+    }
+}
+
 /**
  * Wraps all target methods with additional logic that check that this methods will called after `initialize` method
  *
@@ -48,11 +71,15 @@ function wrapTargetMethodsInInitializedCheck (target: IInitializable, initialize
     const ownPropertyNames: string[] = Object.getOwnPropertyNames(target);
     const prohibitedPropertyNames: string[] = [initializeMethodName, constructorMethodName];
 
-    target[initializedTargetMetadataKey] = false;
-
     ownPropertyNames.forEach((propertyName: string) => {
+        const initializablePropertiesSet: Set <string | symbol> = Reflect
+            .getMetadata(initializablePropertiesSetMetadataKey, target);
+        const wrappedMethodsSet: Set <string | symbol> = Reflect
+            .getMetadata(wrappedMethodsSetMetadataKey, target);
+
         const isProhibitedPropertyName: boolean = prohibitedPropertyNames.includes(propertyName)
-            || target[initializablePropertiesSetMetadataKey].has(propertyName);
+            || initializablePropertiesSet.has(propertyName)
+            || wrappedMethodsSet.has(propertyName);
 
         if (isProhibitedPropertyName) {
             return;
@@ -71,13 +98,15 @@ function wrapTargetMethodsInInitializedCheck (target: IInitializable, initialize
         Object.defineProperty(target, propertyName, {
             ...methodDescriptor,
             value: function (): void {
-                if (!this[initializedTargetMetadataKey]) {
+                if (!Reflect.getMetadata(initializedTargetMetadataKey, this)) {
                     throw new Error(`Class should be initialized with \`${initializeMethodName}()\` method`);
                 }
 
-                originalMethod.apply(this, arguments);
+                return originalMethod.apply(this, arguments);
             }
         });
+
+        wrappedMethodsSet.add(propertyName);
     });
 }
 
@@ -100,11 +129,13 @@ function wrapInitializeMethodInInitializeCheck (
     Object.defineProperty(target, initializeMethodName, {
         ...methodDescriptor,
         value: function (): void {
-            originalMethod.apply(this, arguments);
+            const result: any = originalMethod.apply(this, arguments);
 
-            this[initializedTargetMetadataKey] = true;
+            Reflect.defineMetadata(initializedTargetMetadataKey, true, this);
 
             if (this[propertyKey]) {}
+
+            return result;
         }
     });
 }
@@ -117,7 +148,10 @@ function wrapInitializeMethodInInitializeCheck (
  * @returns {PropertyDescriptor}
  */
 function wrapInitializableProperty (target: IInitializable, propertyKey: string | symbol): PropertyDescriptor {
-    target[initializablePropertiesSetMetadataKey].add(propertyKey);
+    const initializablePropertiesSet: Set <string | symbol> = Reflect
+        .getMetadata(initializablePropertiesSetMetadataKey, target);
+
+    initializablePropertiesSet.add(propertyKey);
 
     const initializablePropertyMetadataKey: string = `_${propertyKey}`;
     const propertyDescriptor: PropertyDescriptor = Object

+ 2 - 0
src/storages/custom-node-group/CustomNodeGroupStorage.ts

@@ -60,5 +60,7 @@ export class CustomNodeGroupStorage extends MapStorage <ICustomNodeGroup> {
 
             this.storage.set(customNodeGroupName, customNodeGroup);
         });
+
+        console.log(123, this.constructor.name);
     }
 }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است