2016-12-30 4 views
4

Je fais un plugin pour Aurelia et ont besoin d'un décorateur de classe quitapuscrit décorateur de classe qui modifie instance d'objet

  1. ajoute des attributs à la nouvelle instance d'objet, et
  2. appelle une fonction externe avec le nouvel objet comme argument.

Je l'ai regardé à travers des exemples, et jusqu'à présent, je l'ai mis en place ("pseudo-ish" Code)

return function addAndCall(target: any): any { 
    var original = target; 

    var newConstructor = function (...args) { 
     original.apply(this, args); 
     this.newAttribute = "object instance value"; 
     ExternalModule.externalFunction(this); 
    }; 

    newConstructor.prototype = Object.create(original.prototype); 
    newConstructor.prototype.constructor = original; 

    return <any>newConstructor; 
} 

mais

  • Je ne suis pas tout à fait clair sur les détails ici (ou ce qui est réellement nécessaire), et
  • il pourrait ne pas fonctionner correctement puisque j'obtiens des erreurs d'Aurelia en utilisant des objets instanciés des classes avec ce décorateur (et je suspecte que c'est mon décorateur plutôt que l'Aurelia cadre qui est buggé).

Toute aide et explication seraient grandement appréciées!

Répondre

2

Pourquoi ne pas simplement attribuer ces propriétés au prototype, puis attribuer à l'instance sur la première invocation

// decorator 
function addAndCall(cb: Function, newField: string) { 
    // cb is now available in the decorator 
    return function(ctor: Function): void { 

    Object.defineProperty(ctor.prototype, newField, { 
     value: function(...args: any[]) { 
     return Object.defineProperty(this, newField, { 

      value: function(...args: any[]) { 
      console.log(newField, ...args); 
      } 

     })[newField](...args); 
     } 
    }); 
    cb(ctor); 
    } 
} 

let callMe = (decoratedCtor) => console.log(decoratedCtor); 
@addAndCall(callMe, 'propertyName') 
class AddToMe {} 

let addToMe = new AddToMe(); 
(<any>addToMe).propertyName(1, 2); 
+0

souhaits Je l'avais vu plus tôt - cela m'a pris des heures pour arriver à cela. –

1

Voici une version de travail:

function addAndCall(target: any) { 
    var original = target; 

    function construct(constructor, args) { 
     var c: any = function() { 
      this.newAttribute = "object instance value"; 
      ExternalModule.externalFunction(this); 
      return constructor.apply(this, args);; 
     } 

     c.prototype = constructor.prototype; 
     return new c(); 
    } 

    var f: any = function (...args) { 
     return construct(original, args); 
    } 

    f.prototype = original.prototype; 
    return f; 
} 

(code in playground)