class Test {
@First()
@Second()
public someAttribute;
}
var t = new Test();
var decorators = t.getListOfAttributeDecorators("someAttribute");
console.log(decorators); // [First, Second]
Run Code Online (Sandbox Code Playgroud)
我想实现“getListOfAttributeDecorators”函数,但不知道如何实现。或者有没有其他方法可以获取属性装饰器列表?
myk*_*iuk 10
You can get data about your custom decorators using reflect-metadata. It's possible by defining metadata of property inside decorator's implementation -
see on codesandbox. You can do it only with your custom decorators however third-party libs often also use such approach with a different 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);
Run Code Online (Sandbox Code Playgroud)
Don't forget to add "emitDecoratorMetadata": true to your tsconfig.json in order to be able to manipulate with metadata.
Bonus: implementation with class decorators support - see on codesandox
P.S. It's the old question, however, I hope my answer will help someone.
您需要维护一个保存该信息的数据结构,例如:
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"]
Run Code Online (Sandbox Code Playgroud)
(操场上的代码)
| 归档时间: |
|
| 查看次数: |
6348 次 |
| 最近记录: |