0

我在字段装饰器中使用反射有问题。我创建了一个具有以下签名的装饰器:

export function Inject() {
    return function (clazz, name) {
        .......
        let typeName: string = Reflect.getOwnMetadata("design:type", clazz, name).name;
        .........
    }
}

class MyClass{
    @Inject()
    private $q:ng.IQService
}

我在字段上使用@Inject。它在字段类型为类时有效,但当字段类型为接口时,它返回Function的不是接口的名称。我该如何解决?

4

1 回答 1

1

正如我在评论中所写,接口不是编译后的 js 的一部分,它们只是由编译器使用,然后编译器从输出中发出它们。
由于装饰器是在运行时执行的,因此没有关于您正在装饰的接口的信息。

装饰器文档(元数据部分)的最后一个示例中,他们表明这样做:

class MyClass {
    @MyDeco
    myMember: MyType;
}

相当于做:

class MyClass {
    @MyDeco
    @Reflect.metadata("design:type", MyType)
    myMember: MyType;
}

这是因为如果您自己不包含该@Reflect.metadata部分,那么编译器会为您添加该部分。

但是当MyType是一个接口时,编译器会将它替换为Object,所以:

interface MyInterfaceType {}

class MyClassType {}

class MyClass {
    @MyDeco
    member1: MyClassType;

    @MyDeco
    member2: MyInterfaceType;
}

编译为:

var MyClass = (function () {
    function MyClass() {
    }
    __decorate([
        MyDeco, 
        __metadata('design:type', MyClassType)
    ], MyClass.prototype, "member1", void 0);
    __decorate([
        MyDeco, 
        __metadata('design:type', Object)
    ], MyClass.prototype, "member2", void 0);
    return MyClass;
}());

如果您想继续使用接口并拥有它们的名称,那么我建议您为您的装饰器提供一个可选参数,该参数将接收名称,然后在接口上使用此装饰器时只需将名称放在那里。
我知道它有点错过了重点,但你并没有更多的选择(正如我所看到的那样)。

于 2016-09-05T11:09:40.207 回答