2016-12-14 2 views
0
class Test { 
    @First() 
    @Second() 
    public someAttribute; 
} 

var t = new Test(); 
var decorators = t.getListOfAttributeDecorators("someAttribute"); 
console.log(decorators); // [First, Second] 

"getListOfAttributeDecorators"함수를 구현하고 싶습니다. 그러나 어떻게 알지 못합니다. 아니면 속성 데코레이터 목록을 가져 오는 다른 방법이 있습니까?TypeScript에서 속성 데코레이터 목록 가져 오기

답변

1
당신은 정보, 같은 유지하는 데이터 구조를 유지해야합니다

:

const REGISTRY = new Map<string, Map<string, string[]>>(); 
function register(cls: string, property: string, decorator: string) { 
    let map: Map<string, string[]>; 

    if (REGISTRY.has(cls)) { 
     map = REGISTRY.get(cls); 
    } else { 
     map = new Map<string, string[]>(); 
     REGISTRY.set(cls, map); 
    } 

    let list: string[]; 
    if (map.has(property)) { 
     list = map.get(property); 
    } else { 
     list = []; 
     map.set(property, list); 
    } 

    if (list.indexOf(decorator) < 0) { 
     list.push(decorator); 
    } 
} 

function First() { 
    return function (cls: any, property: string) { 
     register(cls.constructor.name, property, "First"); 
    } 
} 

function Second() { 
    return function (cls: any, property: string) { 
     register(cls.constructor.name, property, "Second"); 
    } 
} 

class Test { 
    @First() 
    @Second() 
    public someAttribute; 

    public getListOfAttributeDecorators(property: string): string[] { 
     const name = this.constructor.name; 
     return !REGISTRY.has(name) ? [] : REGISTRY.get(name).get(property); 
    } 
} 

let t = new Test(); 
let names = t.getListOfAttributeDecorators("someAttribute"); 
console.log(names); // ["Second", "First"] 

(code in playground)

0

당신은 reflect-metadata를 사용하여 사용자 정의 장식에 대한 데이터를 얻을 수 있습니다. 데코레이터 구현 내에서 속성의 메타 데이터를 정의하면 가능합니다. see on codesandbox. 당신은 종종 메타 데이터를 조작 할 수 있도록 여러분의 tsconfig.json"emitDecoratorMetadata": true를 추가하는 것을 잊지 마세요 다른 metadata key

// be sure to import reflect-metadata 
// without importing reflect-metadata Reflect.defineMetadata and other will not be defined. 
import "reflect-metadata"; 

function First(target: Object, propertyKey: string | symbol) { 
    // define metadata with value "First" 
    Reflect.defineMetadata("custom:anotations:first", "First", target, propertyKey); 
} 

function Second(target: Object, propertyKey: string | symbol) { 
    // define metadata with value { second: 2 } 
    // be sure that metadata key is different from First 
    Reflect.defineMetadata("custom:anotations:second", { second: 2 }, target, propertyKey); 
} 

class Test { 
    @First 
    @Second 
    someAttribute: string; 
} 

// get decorators 

function getDecorators(target: any, propertyName: string | symbol): string[] { 
    // get info about keys that used in current property 
    const keys: any[] = Reflect.getMetadataKeys(target, propertyName); 
    const decorators = keys 
    // filter your custom decorators 
    .filter(key => key.toString().startsWith("custom:anotations")) 
    .reduce((values, key) => { 
     // get metadata value. 
     const currValues = Reflect.getMetadata(key, target, propertyName); 
     return values.concat(currValues); 
    }, []); 

    return decorators; 
} 

// test 

var t = new Test(); 
var decorators = getDecorators(t, "someAttribute"); // output is [{ second: 2}, "First"] 
console.log(decorators); 

과 같은 방법을 사용할 만하지만 사용자 정의 장식 타사 libs와 함께 할 수 있습니다.

보너스 : - see on codesandox

P.S. class decorators 지원 구현 그것은 오래된 질문이지만, 나는 나의 대답이 누군가를 도울 것이기를 바랍니다.

관련 문제