简体   繁体   English

如何为属性创建TypeScript @Relationship装饰器

[英]How to create a TypeScript @Relationship decorator for a property

Consider the following code: 考虑以下代码:

export class Model {
    constructor(input: any) {
        this.deserialize(input);
    }

    deserialize(input: any): Model {
        Object.assign(this, input);
        return this;
    }
}

export class Body extends Model {
    Success: boolean;
    @Relationship Result: Result;
    //...
}

export class Result extends Model {
    Skip: number;
    Top: number;
    TotalCount: number;
    //...
}

The script receives a json and starts a new instance of the Body class: 该脚本接收一个json并启动Body类的新实例:

//...
let body = new Body({
    Sucess: true,
    Result: {
        Skip: 0,
        Top: 0,
        TotalCount: 20
        //...
    }
    //...
});

The deserialize method is used to copy the values of all enumerable own properties from one or more source objects to a target object. deserialize方法用于将所有可枚举的自身属性的值从一个或多个源对象复制到目标对象。 It will return the target object. 它将返回目标对象。

For the Result property to start correctly, a change is required in the deserialize method: 为了使Result属性正确启动,需要在deserialize方法中进行以下更改:

deserialize(input: any): Model {
    Object.assign(this, input);
    this.Result = new Result(input.Result);
    return this;
}

The problem that the Model class is generic and can not implement the solution described. Model类是通用的,无法实现所描述的解决方案。

I do not want to declare the deserialize method on each child class. 我不想在每个子类上声明deserialize方法。

As the problem can be solved using the decorator "@Relationship"? 使用装饰器“ @Relationship”可以解决问题吗?

Yes, it is possible. 对的,这是可能的。 There detailed example , that does something similar, and there detailed description (russian), how it works 这里有详细的示例 ,它执行类似的操作,并有详细的描述 (俄语),它是如何工作的

In short, you should do next: 简而言之,您应该执行以下操作:

  1. Enable emitDecoratorsMetadata in tsconfig and install reflect-metadata polyfill. 在tsconfig中启用emitDecoratorsMetadata并安装反射元数据 polyfill。
  2. In decorator mark field, by applying metadata via call Reflect.defineMetadata("SomeUniqueDecoratorKey", true, target, fieldName) 在装饰器标记字段中,通过调用Reflect.defineMetadata(“ SomeUniqueDecoratorKey”,true,target,fieldName)应用元数据
  3. In deserialize function iterate through fields, and check if SomeUniqueDecoratorKey metadata is true for this field. 在反序列化功能中,对字段进行迭代,然后检查此字段的SomeUniqueDecoratorKey元数据是否为true。 If it is true, then get field type constructor and create new instance. 如果为true,则获取字段类型构造函数并创建新实例。

      var fieldTypeCtor = Reflect.getMetadata("design:type", target, fieldName); var newInstance = new fieldTypeCtor(yourData); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM