用于派生类的Typescript方法装饰器

时间:2017-11-09 06:51:38

标签: typescript architecture decorator

我对' h.collection'的期望是[[' a',alpha],[' b',beta]], 并且对于' w.collection'是[[' a',alpha],[' c',gama]]。

但是Greeter,Hello和World都只是分享了相同的#39;对吧?

那么,我应该更改哪些代码?

function alias(alias: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        let func = target[propertyKey];
        func.alias = alias;
        if (!target.collection) {
            target.collection = new Map();
        }
        target.collection.set(alias, func);
    };
}

abstract class Greeter {
    public collection: Map<string, Function>;
    @alias('a')
    alpha(){}
}

class Hello extends Greeter {
    @alias('b')
    beta(){}
}

class World extends Greeter {
    @alias('c')
    gama(){}
}

let h = new Hello();
let w = new World();

console.log(h.collection);
console.log(w.collection);

1 个答案:

答案 0 :(得分:0)

这是我对于解决方案的尴尬解决方案。这是我能做出的最优雅的方式。

function alias(alias: string) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        let className: string = target.constructor.name;
        let func = descriptor.value;
        func.alias = alias;

        target.shadowCollections = target.shadowCollections || {}
        let shadowCollections = target.shadowCollections;

        shadowCollections[className] = shadowCollections[className] || new Map();
        let collection: Map<string, Function> = shadowCollections[className];

        collection.set(alias, func);
    };
}

function fix<T extends { new(...args: any[]): {} }>(ctor: T) {
    let all: [string, Function][] = [];
    function* getClassNames(_ctor: T) {
        while (_ctor && _ctor.name) {
            yield _ctor.name;
            _ctor = Object.getPrototypeOf(_ctor);
        }
    }
    for (let className of getClassNames(ctor)) {
        let current: Map<string, Function> = ctor.prototype.shadowCollections[className];
        all.push(...current);
    }
    all.sort(([a,], [b,]) => a < b ? -1 : (a > b ? 1 : 0));
    delete ctor.prototype.shadowCollections;
    return class extends ctor {
        _collection = new Map(all);
    }
}

abstract class Greeter {
    protected _collection: Map<string, Function>;
    public get collection(): Map<string, Function> {
        return this._collection;
    }
    @alias('a')
    alpha() { }
}

@fix
class Hello extends Greeter {
    @alias('b')
    beta() { }
}

@fix
class World extends Greeter {
    @alias('c')
    gama() { }
}

let h = new Hello();
let w = new World();

console.log(h.collection);
console.log(w.collection);
相关问题