2017-02-16 3 views
5

In Typoskript ist es möglich, einen Property Decorator zu verwenden, um Metadaten für die Klasse festzulegen? Betrachten Sie den folgenden Code. Das "Ziel" des Klassendekorators ist offensichtlich nicht das gleiche wie das "Ziel" des Eigenschaftsdekorators. Kann ich eines von dem anderen ableiten?kann Typoskript-Eigenschaft Dekoratoren setzen Metadaten für die Klasse?

import 'reflect-metadata'; 


const MY_CLASS_DECORATOR_KEY = 'MyClassDecoratorKey'; 
const MY_PROPERTY_DECORATOR_KEY = 'MyPropertyDecoratorKey'; 

export const MyClassDecorator = options => { 
    return function (target) { 
     console.log('class target: ' , target); 
     Reflect.defineMetadata(MY_CLASS_DECORATOR_KEY, options, target); 
    }; 
}; 

export const MyPropertyDecorator = (options): PropertyDecorator => { 
    return (target, property) => { 
     console.log('property target: ' , target); 
     const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, target) || {}; 
     metadata[property] = options; 
     Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, target); 
    }; 
}; 

@MyClassDecorator('my class decorator value') 
class MyClass { 
    @MyPropertyDecorator('first my property decorator value') 
    myFirstProperty: any; 

    @MyPropertyDecorator('second my property decorator value') 
    mySecondProperty: any; 
} 

console.log('keys: ', Reflect.getMetadataKeys(MyClass)); 

Beachten Sie die Ausgabe:

property target: MyClass {} 
property target: MyClass {} 
class target: function MyClass() { 
    } 
keys: [ 'MyClassDecoratorKey' ] 

Wie kann ich die Metadaten Schlüssel erhalten auch Schlüssel aus dem Eigentum Dekorateur zeigen?

Antwort

3

Ja, Sie können tun, was Sie wollen in Ihrem Dekorateur, aber wie Sie herausgefunden haben, ist Ihr Problem mit dem Ziel, das Sie übergeben werden.

Grundsätzlich in einer Eigenschaft Dekorateur, die target Parameter ein von zwei Dingen sein können, je nachdem, ob der Dekorateur auf einer statischen Eigenschaft oder eine Instanz Eigenschaft verwendet wird:

auf einer statische Eigenschaft, die target Eigenschaft wird die Klassenkonstruktorfunktion. Dies bedeutet, dass das Ziel auf einer statischen Eigenschaft genauso ist wie es für Ihren Klassendekorator der Fall ist.

Bei einer Exemplareigenschaft ist der target-Parameter jedoch der von Ihnen erstellten Klasse, nicht der Konstruktor. Aus diesem Grund sehen Sie das Verhalten, das Sie sehen. Im Falle einer Instanzeigenschaft werden Ihre Metadaten nicht an die constructor angehängt, wie dies bei Ihrem Klassendekorator der Fall ist.

Es gibt jedoch immer noch Hoffnung, denn Sie können leicht die Konstruktorfunktion für eine Prototypinstanz aufrufen, wie sie in einer Eigenschaft namens constructor gespeichert ist. Also in Ihrem Fall können Sie das Verhalten erhalten Sie diese suchen, indem Sie:

export const MyPropertyDecorator = (options): PropertyDecorator => { 
    return (target, property) => { 
     var classConstructor = target.constructor; 
     console.log('property target: ' , classConstructor); 
     const metadata = Reflect.getMetadata(MY_PROPERTY_DECORATOR_KEY, classConstructor) || {}; 
     metadata[property] = options; 
     Reflect.defineMetadata(MY_PROPERTY_DECORATOR_KEY, metadata, classConstructor); 
    }; 
}; 

HINWEIS: die obige Änderung zum Beispiel Eigenschaften funktionieren würde, aber nicht statische Eigenschaften. Wenn Sie beide Arten von Eigenschaften behandeln müssen, müssen Sie einige zusätzliche Logik hinzufügen, um festzustellen, ob target oder target.constructor

+0

Oh fantastisch zu verwenden ist. Ihre Antwort ist genau das, was ich brauchte. Vielen Dank! Aber angenommen, ich wollte in die andere Richtung gehen und die Metadaten anstelle des Konstruktors auf den Prototyp setzen? Kann ich die andere Richtung gehen? – bkinsey808

+0

Sicher, tun Sie einfach target.prototype – dtabuenc

Verwandte Themen